转自:http://www.hangge.com/blog/cache/detail_1638.html
2015年6月, ES2015(即 ECMAScript 6、ES6) 正式发布。其中 Promise 被列为正式规范,成为 ES6 中最重要的特性之一。
1,then()方法
简单来讲,then 方法就是把原来的回调写法分离出来,在异步操作执行完后,用链式调用的方式执行回调函数。
而 Promise 的优势就在于这个链式调用。我们可以在 then 方法中继续写 Promise 对象并返回,然后继续调用 then 来进行回调操作。
(1)下面通过样例作为演示,我们定义做饭、吃饭、洗碗(cook、eat、wash)这三个方法,它们是层层依赖的关系,下一步的的操作需要使用上一部操作的结果。(这里使用 setTimeout 模拟异步操作)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
|
(2)使用 then 链式调用这三个方法:
1 2 3 4 5 6 7 8 9 10 |
|
当然上面代码还可以简化成如下:
1 2 3 4 5 6 |
|
(3)运行结果如下:
2,reject()方法
上面样例我们通过 resolve 方法把 Promise 的状态置为完成态(Resolved),这时 then 方法就能捕捉到变化,并执行“成功”情况的回调。
而 reject 方法就是把 Promise 的状态置为已失败(Rejected),这时 then 方法执行“失败”情况的回调(then 方法的第二参数)。
(1)下面同样使用一个样例做演示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
运行结果如下:
(2)如果我们只要处理失败的情况可以使用 then(null, ...),或是使用接下来要讲的 catch 方法。
1 2 3 4 |
|
3,catch()方法
(1)它可以和 then 的第二个参数一样,用来指定 reject 的回调
1 2 3 4 5 |
|
(2)它的另一个作用是,当执行 resolve 的回调(也就是上面 then 中的第一个参数)时,如果抛出异常了(代码出错了),那么也不会报错卡死 js,而是会进到这个 catch 方法中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
运行结果如下:
这种错误的捕获是非常有用的,因为它能够帮助我们在开发中识别代码错误。比如,在一个 then() 方法内部的任意地方,我们做了一个 JSON.parse() 操作,如果 JSON 参数不合法那么它就会抛出一个同步错误。用回调的话该错误就会被吞噬掉,但是用 promises 我们可以轻松的在 catch() 方法里处理掉该错误。
(3)还可以添加多个 catch,实现更加精准的异常捕获。
1 2 3 4 5 6 7 8 9 10 11 |
|
4,all()方法
Promise 的 all 方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调。
(1)比如下面代码,两个个异步操作是并行执行的,等到它们都执行完后才会进到 then 里面。同时 all 会把所有异步操作的结果放进一个数组中传给 then。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
(2)运行结果如下:
5,race()方法
race 按字面解释,就是赛跑的意思。race 的用法与 all 一样,只不过 all 是等所有异步操作都执行完毕后才执行 then 回调。而 race 的话只要有一个异步操作执行完毕,就立刻执行 then 回调。
注意:其它没有执行完毕的异步操作仍然会继续执行,而不是停止。
(1)这里我们将上面样例的 all 改成 race
1 2 3 4 5 6 |
|
(2)race 使用场景很多。比如我们可以用 race 给某个异步请求设置超时时间,并且在超时后执行相应的操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
上面代码 requestImg 函数异步请求一张图片,timeout 函数是一个延时 5 秒的异步操作。我们将它们一起放在 race 中赛跑。
- 如果 5 秒内图片请求成功那么便进入 then 方法,执行正常的流程。
- 如果 5 秒钟图片还未成功返回,那么则进入 catch,报“图片请求超时”的信息。
原文出自:www.hangge.com 转载请保留原文链接:http://www.hangge.com/blog/cache/detail_1638.html#
对js Promise理解
1.优点和缺点
可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。
Promise也有一些缺点。首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
2.规范
Promise 对象有三种状态: Pending – Promise对象的初始状态,等到任务的完成或者被拒绝;Resolved – 任务执行完成并且成功的状态;Rejected – 任务执行完成并且失败的状态;
Promise的状态只可能从Pending状态转到Resolved状态或者Rejected状态,而且不能逆向转换,同时Resolved状态和Rejected状态也不能相互转换;
Promise对象必须实现then方法,then是promise规范的核心,而且then方法也必须返回一个Promise对象,同一个Promise对象可以注册多个then方法,并且回调的执行顺序跟它们的注册顺序一致;
then方法接受两个回调函数,它们分别为:成功时的回调和失败时的回调;并且它们分别在:Promise由Pending状态转换到Resolved状态时被调用和在Promise由Pending状态转换到Rejected状态时被调用。
3.特性
3-1.立即执行性
-
var p=new Promise(function(resolve,reject)(){
-
console.log("create new promise");
-
resolve("success");
-
});
-
console.log("after new promise");
-
p.then(function(value){
-
console.log(value);
-
});
-
//create new promise
-
//after new promise
-
//success
3-2.状态不可逆性、链式调用、
-
var p = new Promise(function(resolve, reject){
-
resolve(1);
-
});
-
p.then(function(value){ //第一个then
-
console.log(value);
-
return value*2;
-
}).then(function(value){ //第二个then
-
console.log(value);
-
}).then(function(value){ //第三个then
-
console.log(value);
-
return Promise.resolve('resolve');
-
}).then(function(value){ //第四个then
-
console.log(value);
-
return Promise.reject('reject');
-
}).then(function(value){ //第五个then
-
console.log('resolve: '+ value);
-
}, function(err){
-
console.log('reject: ' + err);
-
})
-
//1
-
//2
-
//undefined
-
//resolve
-
//reject: reject
3-3.then() 回调异步性
-
var p = new Promise(function(resolve, reject){
-
resolve("success");
-
});
-
p.then(function(value){
-
console.log(value);
-
});
-
console.log("first");
-
//"first"
-
//"success"
4.用法
-
function getURL(URL) {
-
return new Promise(function (resolve, reject) {
-
var req = new XMLHttpRequest();
-
req.open('GET', URL, true);
-
req.onload = function () {
-
if (req.status === 200) {
-
resolve(req.responseText);
-
} else {
-
reject(new Error(req.statusText));
-
}
-
};
-
req.onerror = function () {
-
reject(new Error(req.statusText));
-
};
-
req.send();
-
});
-
}
-
// 运行示例
-
var URL = "http://httpbin.org/get";
-
getURL(URL).then(function onFulfilled(value){
-
console.log(value);
-
}).catch(function onRejected(error){
-
console.error(error);
-
});