Promise执行顺序

2021-08-03  本文已影响0人  薯条你哪里跑

这段代码执行后,分别打印出来什么?

let v = new Promise(resolve => {
      console.log("begin");
      resolve("then");
    });
new Promise(resolve => {
      resolve(v);
    }).then((v)=>{
        console.log(v)
    }); 
new Promise(resolve => {
      console.log(1);
      resolve();
    }) .then(() => {
        console.log(2);
    }).then(() => {
        console.log(3);
    }) .then(() => {
        console.log(4);
   })

答案:

begin
1
2
3
then
4

刚开始看这个问题的时候这个 then和4的顺序很让我迷惑。
后来看了很多文章,这里resolve(v), v是一个promise属于thenable对象。

new Promise(resolve => {
      // v是一个thenable
      resolve(v);
    }).then((v)=>{
        console.log(v)
});
//  执行起来相当于,及有两个then往后推了两个微任务。
new Promise(resolve => {
      Promise.resolve().then(()=>{
            v.then(resolve)
      })
    }).then((v)=>{
        console.log(v)
});


var a = Promise.resolve(true)
//same as
var a = new Promise(function(resolve,reject){
    //立即变成成功状态
    resolve(true)
})

var b = Promise.reject(true)
//same as
var b = new Promise(function(resolve,reject){
    //立即变成失败状态
    reject(true)
})
在 Promise 中 resolve 一个 Promise 实例解析:
最终结果就是:额外创建了两个Job,表现上就是后续代码被推迟了2个时序

对于 new Promise(resolve => resolve(thenable)),即“在 Promise 中 resolve 一个 thenable 对象”,需要先将 thenable 转化为 Promsie,然后立即调用 thenable 的 then 方法,并且 这个过程需要作为一个 job 加入微任务队列,以保证对 then 方法的解析发生在其他上下文代码的解析之后。

let thenable = {
  then(resolve, reject) {
    console.log('in thenable');
    resolve(100);
  }
};

new Promise((r) => {
  console.log('in p0');
  r(thenable);
})
.then(() => { console.log('thenable ok') })

new Promise((r) => {
  console.log('in p1');
  r();
})
.then(() => { console.log('1') })
.then(() => { console.log('2') })
.then(() => { console.log('3') })
.then(() => { console.log('4') });

执行顺序:

in p0
in p1
in thenable
1
thenable ok
2
3
4

解析:

参考:令人费解的 async/await 执行顺序
测试: https://segmentfault.com/a/1190000022805523

https://segmentfault.com/a/1190000022805523

再来一个await

async function async1() {
    console.log('async1 start')
    await async2()
    console.log('async1 end')
}
    
async function async2() {
    console.log('async2')
}
    
console.log('script start')

setTimeout(function () {
    console.log('setTimeout')
}, 0)
    
async1();
    
new Promise(function (resolve) {
    console.log('promise1')
    resolve()
}).then(function () {
    console.log('promise2')
})
    
console.log('script end')

答案:

script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout

梳理下await函数的执行时机,我们可以看看这篇文章:《「译」更快的 async 函数和 promises》,下面引入其中的一些描述:

简单说,await v 初始化步骤有以下组成:

  1. 把 v 转成一个 promise(跟在 await 后面的)。
  2. 绑定处理函数用于后期恢复。
  3. 暂停 async 函数并返回 implicit_promise 给调用者。

我们一步步来看,假设 await 后是一个 promise,且最终已完成状态的值是 42。然后,引擎会创建一个新的 promise 并且把 await 后的值作为 resolve 的值。借助标准里的 PromiseResolveThenableJob 这些 promise 会被放到下个周期执行。

结合规范和这篇文章,简单总结一下,对于 await v:

function async1(){
  console.log('async1 start')
  return new Promise((resolve,reject)=>{
      resolve(async2())
  }).then(() => {
      console.log('async1 end')
  });
}

即await下面的代码被拖到了微任务队列中。

上一篇下一篇

猜你喜欢

热点阅读