Promise的设计初衷
我们使用ajax请求数据,得到数据后再对数据进行操作,可是有时候,对得到的数据进行操作的过程中,可能又要用到ajax请求,这时,我们的代码就变成了这样:
$.ajax({
success:function(res1){
//...请求B开始,B依赖A返回的数据
$.ajax({
sucess:function(res2){
//...请求C开始,C依赖B返回的数据
$.ajax({
sucess:function(res3){
}
});
}
});
}
});
这种写法的不足:
(1)当多个请求层层依赖的话,就会很多层嵌套,代码的可读性会变得很差,也不利于调试,当一个逻辑层修改的时候可能会引起多个层的变化。
(2)如果C依赖于A和B的结果,但A,B彼此独立,按照上边的写法,B也要等A执行完之后才可以执行,消耗了更多的等待时间。
为了避免这种回调函数层层嵌套(回调地狱)的形式,ES6 给出了Promise。
- Promise对象能使我们更加合理、更加规范的进行异步操作。
下面我们来正式介绍Promise。
(1)Promise的基本用法:
let pro=new Promise(function(resolve,reject){
});
Promise对象是一个全局对象,创建Promise实例的时候,参数是一个匿名函数,其中有两个参数:resolve,reject。
这两个参数均为方法,resolve方法处理一步操作成功后的业务,reject方法处理业务操作失败后的业务。
(2)Promise的三种状态
- pending:刚刚创建一个Promise实例的时候,表示初始状态。
- fulfilled:resolve方法调用的时候,表示操作成功。
- rejected:reject方法调用的时候,表示操作失败
状态的转化只能是:初始态(pending)->成功(fulfilled),或者,初始态(pending) ->失败(rejected) (不能逆向转换,也无法在成功与失败之间转换)
let pro=new Promise(function(resolve,reject){
//实例化后的状态:pending
if(成功){
resolve(); //状态:fulfiled
}else{
reject(); //状态 : rejected
}
});
(3)then()方法
用于绑定处理操作后的处理程序。
pro.then(function(res){
//操作成功的处理程序
},function(error){
//操作失败的处理程序
})
(3)catch()方法
对于操作异常的程序,使用catch()方法。
pro.catch(function(error){
//操作失败的处理程序
});
当操作层层依赖的时候,Promise的处理方法:
看一个完整的案例:
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('Aok');
return 'next B';
}
function requestB(res){
console.log('Aresult:'+res);
console.log('Bok')
return 'next C';
}
function requestC(res){
console.log('Bresult:'+res);
console.log('Cok')
}
function requestError(){
console.log('false');
}
//结果:
Aok
Aresult:next B
Bok
Bresult:next C
Cok
可以看出,使用then方法,三个请求不必在层层嵌套。当B依赖A时,我们使用return将A的结果返回,B使用参数接受这个结果
几个重要的方法:
(1)Promise.all()
接受一个数组作为参数,数组的元素是Promise实力对象,当参数中对象的状态全部返回fulfilled的时候,Promise才会返回。
let pro1=new Promise(function(resolve){
setTimeout(function(){
resolve('eg1_ok');
},5000);
});
let pro2=new Promise(function(resolve){
setTimeout(function(){
resolve('eg2_ok');
},2000);
});
Promise.all([pro1,pro2]).then(function(result){
console.log(result); //['eg1_ok','eg2_ok']
}) //在等待pro1,pro2都进入fulfilled状态(5000ms)后,promise.all() 才执行。
当我们执行的某个操作需要多个接口返回的数据来支持,而这多个接口又是互不依赖的,这时候我们就可以用Promise.all(),它会在所有的接口都请求成功后才操作。
(2)Promise.race()方法
与Promise.all()的区别在于,所有的参数实例中,只要又一个状态变化(无论成功还是失败),就会执行,其他实例中再发生变化,它也不管了。
let pro1=new Promise(function(resolve){
setTimeout(function(){
resolve('eg1_ok');
},5000);
});
let pro2=new Promise(function(resolve){
setTimeout(function(){
reject('eg2_false');
},2000);
});
Promise.race([pro1,pro2]).then(function(result){
console.log(result);
}).catch(function(error){
console.log(error)
});
//eg2_false
_______________
参考:公众号 web前端教程