学习Promise的使用(一)

156 阅读3分钟

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方法解决。

这是我的一个学习总结,不足之处敬请原谅,欢迎批评指正。