本文大部分内容是阮一峰老师的文章,这里搬过来也是为了自己记录,想看更加详细的教程请移步阮一峰老师个人博客
1.Promise.prototype.then()
then
方法返回的是一个新的Promise
实例(注意,不是原来那个Promise
实例)。因此可以采用链式写法,即then()
方法后面再调用另一个 then()
方法。
getJSON("/posts.json").then(function(json) {
return json.post;
}).then(function(post) {
// ...
});
采用链式的 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)
);
看下面一个使用的综合案例
let pro = new Promise(function(resolve,reject){
if(true){
//调用操作成功方法
resolve('操作成功');
}else{
//调用操作异常方法
reject('操作异常');
}
});
//用then处理操作成功,catch处理操作异常
pro.then(requestA)
.then(requestB)
.then(requestC)
.catch(requestError);
function requestA(){
console.log('请求A成功');
return '请求B,下一个就是你了';
}
function requestB(res){
console.log('上一步的结果:'+res);
console.log('请求B成功');
return '请求C,下一个就是你了';
}
function requestC(res){
console.log('上一步的结果:'+res);
console.log('请求C成功');
}
function requestError(){
console.log('请求失败');
}
//打印结果:
//请求A成功
//上一步的结果:请求B,下一个就是你了
//请求B成功
//上一步的结果:请求C,下一个就是你了
//请求C成功
案例中,先是创建一个实例,还声明了4个函数,其中三个是分别代表着请求A,请求B,请求C;有了then方法,三个请求操作再也不用层层嵌套了。我们使用then方法,按照调用顺序,很直观地完成了三个操作的绑定,并且,如果请求B依赖于请求A的结果,那么,可以在请求A的程序用使用return语句把需要的数据作为参数,传递给下一个请求,案例中我们就是使用return实现传递参数给下一步操作的。
Promise.all( )方法
Promise.all( )
方法:接受一个数组作为参数,数组的元素是Promise
实例对象,当参数中的实例对象的状态都为fulfilled
时,Promise.all( )
才会有返回。
//创建实例pro1
let pro1 = new Promise(function(resolve){
setTimeout(function () {
resolve('实例1操作成功');
},5000);
});
//创建实例pro2
let pro2 = new Promise(function(resolve){
setTimeout(function () {
resolve('实例2操作成功');
},1000);
});
Promise.all([pro1,pro2]).then(function(result){
console.log(result);
});
//打印结果:["实例1操作成功", "实例2操作成功"]
上述案例,我们创建了两个Promise实例:pro1和pro2,我们注意两个setTimeout的第二个参数,分别是5000毫秒和1000毫秒,当我们调用Promise.all( )方法的时候,会延迟到5秒才控制台会输出结果。
因为1000毫秒以后,实例pro2进入了成功fulfilled状态;此时,Promise.all( )还不会有所行动,因为实例pro1还没有进入成功fulfilled状态;等到了5000毫秒以后,实例pro1也进入了成功fulfilled状态,Promise.all( )才会进入then方法,然后在控制台输出:["实例1操作成功","实例2操作成功"]。
这个方法有什么用呢?一般这样的场景:我们执行某个操作,这个操作需要得到需要多个接口请求回来的数据来支持,但是这些接口请求之前互不依赖,不需要层层嵌套。这种情况下就适合使用Promise.all( )方法,因为它会得到所有接口都请求成功了,才会进行操作。
Promise.race( )方法
另一个类似的方法是Promise.race()方法:它的参数要求跟Promise.all( )方法一样,不同的是,它参数中的promise实例,只要有一个状态发生变化(不管是成功fulfilled还是异常rejected),它就会有返回,其他实例中再发生变化,它也不管了。
//初始化实例pro1
let pro1 = new Promise(function(resolve){
setTimeout(function () {
resolve('实例1操作成功');
},4000);
});
//初始化实例pro2
let pro2 = new Promise(function(resolve,reject){
setTimeout(function () {
reject('实例2操作失败');
},2000);
});
Promise.race([pro2,pro1]).then(function(result){
console.log(result);
}).catch(function(error){
console.log(error);
});
//打印结果:实例2操作失败
同样是两个实例,实例pro1不变,不同的是实例pro2,这次我们调用的是失败函数reject。
由于pro2实例中2000毫秒之后就执行reject方法,早于实例pro1的4000毫秒,所以最后输出的是:实例2操作失败。
以上就是对Promise对象的内容讲解,上面提到了一个概念:回调地狱;指的是过多地使用回调函数嵌套,使得调试和维护起来极其的不便。
参考:微信文章教你如何使用ES6的Promise对象
https://segmentfault.com/a/1190000002928371
http://www.cnblogs.com/tugenhua0707/p/7337022.html
网友评论