当前位置:K88软件开发文章中心编程语言JavaScriptECMAScript → 文章内容

ECMAScript 6 Promise对象

减小字体 增大字体 作者:佚名  来源:网上搜集  发布时间:2019-1-15 15:38:38

除了正常的值以外,还可能是另一个Promise实例,表示异步操作的结果有可能是一个值,也有可能是另一个异步操作,比如像下面这样。var p1 = new Promise(function (resolve, reject) { // ...});var p2 = new Promise(function (resolve, reject) { // ... resolve(p1);})上面代码中,p1和p2都是Promise的实例,但是p2的resolve方法将p1作为参数,即一个异步操作的结果是返回另一个异步操作。注意,这时p1的状态就会传递给p2,也就是说,p1的状态决定了p2的状态。如果p1的状态是Pending,那么p2的回调函数就会等待p1的状态改变;如果p1的状态已经是Resolved或者Rejected,那么p2的回调函数将会立刻执行。var p1 = new Promise(function (resolve, reject) { setTimeout(() => reject(new Error('fail')), 3000)})var p2 = new Promise(function (resolve, reject) { setTimeout(() => resolve(p1), 1000)})p2 .then(result => console.log(result)) .catch(error => console.log(error))// Error: fail上面代码中,p1是一个Promise,3秒之后变为rejected。p2的状态在1秒之后改变,resolve方法返回的是p1。此时,由于p2返回的是另一个Promise,所以后面的then语句都变成针对后者(p1)。又过了2秒,p1变为rejected,导致触发catch方法指定的回调函数。Promise.prototype.then()Promise实例具有then方法,也就是说,then方法是定义在原型对象Promise.prototype上的。它的作用是为Promise实例添加状态改变时的回调函数。前面说过,then方法的第一个参数是Resolved状态的回调函数,第二个参数(可选)是Rejected状态的回调函数。then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。getJSON("/posts.json").then(function(json) { return json.post;}).then(function(post) { // ...});上面的代码使用then方法,依次指定了两个回调函数。第一个回调函数完成以后,会将返回结果作为参数,传入第二个回调函数。采用链式的then,可以指定一组按照次序调用的回调函数。这时,前一个回调函数,有可能返回的还是一个Promise对象(即有异步操作),这时后一个回调函数,就会等待该Promise对象的状态发生变化,才会被调用。getJSON("/post/1.json").then(function(post) { return getJSON(post.commentURL);}).then(function funcA(comments) { console.log("Resolved: ", comments);}, function funcB(err){ console.log("Rejected: ", err);});上面代码中,第一个then方法指定的回调函数,返回的是另一个Promise对象。这时,第二个then方法指定的回调函数,就会等待这个新的Promise对象状态发生变化。如果变为Resolved,就调用funcA,如果状态变为Rejected,就调用funcB。如果采用箭头函数,上面的代码可以写得更简洁。getJSON("/post/1.json").then( post => getJSON(post.commentURL)).then( comments => console.log("Resolved: ", comments), err => console.log("Rejected: ", err));Promise.prototype.catch()Promise.prototype.catch方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数。getJSON("/posts.json").then(function(posts) { // ...}).catch(function(error) { // 处理 getJSON 和 前一个回调函数运行时发生的错误 console.log('发生错误!', error);});上面代码中,getJSON方法返回一个Promise对象,如果该对象状态变为Resolved,则会调用then方法指定的回调函数;如果异步操作抛出错误,状态就会变为Rejected,就会调用catch方法指定的回调函数,处理这个错误。另外,then方法指定的回调函数,如果运行中抛出错误,也会被catch方法捕获。p.then((val) => console.log("fulfilled:", val)) .catch((err) => console.log("rejected:", err));// 等同于p.then((val) => console.log("fulfilled:", val)) .then(null, (err) => console.log("rejected:", err));下面是一个例子。var promise = new Promise(function(resolve, reject) { throw new Error('test');});promise.catch(function(error) { console.log(error);});// Error: test上面代码中,promise抛出一个错误,就被catch方法指定的回调函数捕获。注意,上面的写法与下面两种写法是等价的。// 写法一var promise = new Promise(function(resolve, reject) { try { throw new Error('test'); } catch(e) { reject(e); }});promise.catch(function(error) { console.log(error);});// 写法二var promise = new Promise(function(resolve, reject) { reject(new Error('test'));});promise.catch(function(error) { console.log(error);});比较上面两种写法,可以发现reject方法的作用,等同于抛出错误。如果Promise状态已经变成Resolved,再抛出错误是无效的。var promise = new Promise(function(resolve, reject) { resolve('ok'); throw new Error('test');});promise .then(function(value) { console.log(value) }) .catch(function(error) { console.log(error) });// ok上面代码中,Promise在resolve语句后面,再抛出错误,不会被捕获,等于没有抛出。Promise对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获。getJSON("/post/1.json").then(function(post) { return getJSON(post.commentURL);}).then(function(comments) { // some code}).catch(function(error) { // 处理前面三个Promise产生的错误});上面代码中,一共有三个Promise对象:一个由getJSON产生,两个由then产生。它们之中任何一个抛出的错误,都会被最后一个catch捕获。一般来说,不要在then方法里面定义Reject状态的回调函数(即then的第二个参数),总是使用catch方法。// badpromise .then(function(data) { // success }, function(err) { // error });// goodpromise .then(function(data) { //cb // success }) .catch(function(err) { // error });上面代码中,第二种写法要好于第一种写法,理由是第二种写法可以捕获前面then方法执行中的错误,也更接近同步的

上一页  [1] [2] [3] [4]  下一页


ECMAScript 6 Promise对象