Promise
目的:学会使用promise处理异步问题
1、Promise状态
pending(待定),初始状态,既没有被兑现,也没有被拒绝。
fulfilled(已兑现): 意味着操作成功完成。
rejected(已拒绝): 意味着操作失败。
当这些情况之一发生时,我们用 promise 的 then 方法排列起来的相关处理程序就会被调用。如果 promise 在一个相应的处理程序被绑定时就已经被兑现或被拒绝了,那么这个处理程序就会被调用,因此在完成异步操作和绑定处理方法之间不会存在竞争状态。
补充:如果Promise状态为fulfilled,可以使用then方法来处理相关程序;如果Promise状态为rejected,可以使用then方法(使用第二个参数)、catch方法处理相关程序。
2、使用Promise
创建一个Promise
函数p1中放回一个Promise对象,这里我使用setTimeout来代替异步操作。
function p1(){
return new Promise(resolve => {
setTimeout(function(){
resolve('rp1');
console.log('p1');
}, 3000)
})
}
上述代码中resolve('rp1'),是给Promise一个决议,将状态pending改为fulfilled(若使用rejected,则状态改为rejected)。'rp1'是传给then、catch的参数,可供then、catch方法使用。
p1().then((res)=>{
console.log(res);
})
//输出结果p1、rp1
注意:如果Promise状态为pending,是不能调用then、catch方法的。
3、处理多个异步问题
假设现在有这样的需求,想要获取某个县区的信息。而获取县区的信息需要先知道该县区所处的地市,而获取地市信息需要先知道其所处的省份。
存在这样的三级层级关系,我们把获取省份、获取地市、获取县区分别当做一个异步函数,使用Promise来处理它们,分别为p1、p2、p3。(其中p3依赖于p2,p2依赖于p1,即p1->p2->p3)
创建p1、p2、p3
function p1(){
return new Promise(resolve => {
setTimeout(function(){
resolve('rp1');
console.log('p1');
}, 3000)
})
}
function p2(){
return new Promise(resolve => {
setTimeout(function(){
resolve('rp2');
console.log('p2');
}, 2000)
})
}
function p3(){
return new Promise(resolve => {
setTimeout(function(){
resolve('rp3');
console.log('p3');
}, 2500)
})
}
由于p1、p2、p3存在依赖关系,必须按p1、p2、p3这样的执行顺序。
p1().then(res=>{
p2().then(res=>{
p3()
})
})
//输出结果p1、p2、p3
虽然then方法可以控制p1、p2、p3的执行顺序,但是不够美观,推荐使用Async-await,代码如下。
async function p(){
let b1 = await p1()
let b2 = await p2()
let b3 = await p3()
console.log(b1);
console.log(b2);
console.log(b3);
}
p()
//输出结果p1、p2、p3
注意:
使用Promise.all()
let pa = Promise.all([p1(),p2(),p3()])
pa.then((resolve)=>{
console.log("执行成功!", resolve);
})
//输出结果
//p2
//p3
//p1
//执行成功! [ 'rp1', 'rp2', 'rp3' ]
这里需要说明一下,输出的p2、p3、p1,这个是3个Promise的执行顺序(执行顺序按异步函数返回时间);输出的[ 'rp1', 'rp2', 'rp3' ]是3个Promise的返回结果的顺序,Promise.all()的返回结果会和传入的Promise顺序保持一致。(Promise.all是在3个Promise成功返回的情况下,为返回值进行排序,然后输出。)
回到上面的获取区县信息问题
假设省份为地市提供的数据为a
将代码修改如下
let a = ''
function p1(){
return new Promise(resolve => {
setTimeout(function(){
a = 'a1'
resolve('rp1');
console.log('p1');
}, 3000)
})
}
function p2(){
return new Promise(resolve => {
setTimeout(function(){
resolve('rp2');
console.log('p2');
console.log("a:", a);
}, 2000)
})
}
function p3(){
return new Promise(resolve => {
setTimeout(function(){
resolve('rp3');
console.log('p3');
}, 2500)
})
}
let pa = Promise.all([p1(),p2(),p3()])
pa.then((resolve)=>{
console.log("执行成功!", resolve);
})
//执行结果
//p2
//a:
//p3
//p1
显然,由于执行顺序是p2、p3、p1,在执行p2时,p1还没执行,所以a的值是空的。
所以不能通过使用Promise.all()来解决我们上述的问题,多个异步操作并且有数据依赖关系的,可以使用.then方法嵌套或者Async-await方法解决。
这是我的一个学习总结,不足之处敬请原谅,欢迎批评指正。