关于Promise多次.then输出的问题

185 阅读1分钟

刷到一个面试题,如下


Promise.resolve().then(() => {
    console.log(0)
    return Promise.resolve(4)
}).then((res) => {
    console.log(res)
})

Promise.resolve().then(()=> {
    console.log(1)
}).then(() => {
    console.log(2)
}).then(() => {
    console.log(3)
}).then(() => {
    console.log(5)
}).then(() => {
    console.log(6)
})

输出的结果

image.png

居然是 0 1 2 3 4 5 6

查了一下,以下是答案

Js引擎为了让microtask尽快的输出,做了一些优化,连续的多个then(3个)如果没有reject或者resolve会交替执行then而不至于让一个堵太久完成用户无响应,不单单v8这样其他引擎也是这样,因为其实promise内部状态已经结束了。这块在v8源码里有完整的体现。 return Promise这里会出现两个微任务。1、then返回的是一个promise,会调用返回的promisethen方法来获取状态。2、ECMAScript规定如果返回的是一个promise,会额外产生一个微任务来延迟执行。

也就是说

  1. 输出0以后, 返回了 Promise.resolve(4),这里产生了一个微任务,会把这一行放到一个新的微任务队列里面去。后面的 console.log(res) 会等待在 Promise.resolve(4)后面执行。
  2. 然后执行1,2,3, 这里第三个之后就会切换到另一个微任务,也就是第一个Promise 的微任务继续执行。
  3. 然后就会执行到console.log(res), 4.然后再依次往后面执行打印。

所以才会输出上面的0-6依次打印