Promise A+规范

  Promise A+规范产生于2012年左右,它的产生目的就是希望把异步规范化,并解决回调地狱。在该规范之前,对于异步场景的处理使用了大量的回调函数,有的异步场景也可以把函数保存到对象的属性中,以便将来调用,以此看来,之前处理异步的方式并不统一,于是便有了Promise A+的由来,它并不是一个技术,而是一套规范,对后来的ES6的Promise标准制作提供了参考。 Promise A+规范参考官网:​​https://promisesaplus.com/​

对异步处理的进化

  用一张流程图来展示对异步处理的进化:

Promise_执行栈

 Promise

  一个promise就是一个对象,它用于表示一个异步任务,是一个带有then方法的对象。它有三种状态,pending挂起、fufilled完成、rejected失败。不管任何时候,promise都处于这三种状态的一种,状态介绍下图所示:

 Promise_异步处理_02

状态的转换

  任务开始时,始终处于unsettled(未决)阶段的挂起状态,任务在unsettled阶段时可以将其推向settled阶段。比如,当从服务器拿到数据后,我们就从未决阶段推向已决的resolved状态,如果网络不好,导致出错了,我们就从未决阶段推向已决的rejected状态。我们把从未决推向已决的resolved状态的过程,叫做resolve,从未决推向已决的rejected状态的过程,叫做reject。需要主义的是这种状态和阶段的变化是不可逆的,一旦推向了settled就无法修改该阶段的状态。

  1. 当promise处于pending状态时,它可以在任何时候把状态转变俄日fufilled 或 rejected。

  2. 当promise处于fufilled状态时,它无法再次更改到其他状态,它必须是一个值,表示任务完成时的数据,该数据可以是任何Js数据(包括undefined),一旦该值确定则无法修改。

  3. 当promise处于rejected状态时,它无法再次更改到其他状态,它必须是一个值,表示任务失败的原因,该数据可以是任何Js数据(包括undefined),一旦该值确定则无法修改。

  让任务到达rejected状态的方式:

    a. 调用reject

    b. 代码执行报错

    c. 抛出错误

转换状态成功后即任务完成后会附带数据,就是上面提到的值,具体展示由下图所示:

Promise_执行栈_03

 

 

 任务的后续处理 then方法

  对与任务的后续处理,可以通过promise提供的then方法访问到任务完成的值或任务失败的原因。

  then方法可以接收两个参数:



promise.then(onFulfilled, onRejected)


 

  1. onFulfilled 和 onRejected 都是可选参数,如果该两个参数不是一个函数,则必须省略。

  2. 如果 onFulfilled 是一个函数,它会在 promise 到达 fulfilled 状态时被调用,调用该函数时,应该把任务完成时的值作为第一个参数传递进去(该函数只能被调用一次)。

  3. 如果 onRejected 是一个函数,它会在 promise 到达 rejected 状态时被调用,调用该函数时,应该把任务失败的原因作为第一个参数传递进去(该函数只能被调用一次)。

  4. onFulfilled 和 onRejected 是异步的,所以要等到当前执行栈清空后才能别调用。

  5. 可以多次对同一个 promise 调用 then 方法,从而注册多个 onFulfilled 和 onRejected ,then 方法必须再次返回一个 promise:



promise2 = promise1.then(onFulfilled, onRejected);


  再次返回的 promise 的任务状态与 初始的 promise 状态转换时相似。

Promise 面试题

  通过promise 面试题将理论与实践相结合:

  试题一:



const promise = new Promise((resolve, reject) => {
console.log(1)
resolve("a");
resolve("b");
reject("c")
console.log(2)
})
promise.then(data => {
console.log(data)
}, resean => {
console.log(reason)
})
console.log(4)


  试题二:



setTimeout(() => {
console.log(1);
});
var pro = new Promise((resolve, reject) => {
console.log(2);
resolve(3);
console.log(4);
throw 5;
console.log(6);
});

console.log(7);

pro.then(
(data) => {
console.log(data);
},
(reason) => {
console.log(reason);
}
);


  如有问题,可在评论区提出,共同讨论。