刷到一个面试题,如下
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)
})
输出的结果
居然是 0 1 2 3 4 5 6
查了一下,以下是答案
Js引擎为了让microtask尽快的输出,做了一些优化,连续的多个then(3个)如果没有reject或者resolve会交替执行then而不至于让一个堵太久完成用户无响应,不单单v8这样其他引擎也是这样,因为其实promise内部状态已经结束了。这块在v8源码里有完整的体现。
return Promise这里会出现两个微任务。1、then返回的是一个promise,会调用返回的promise的then方法来获取状态。2、ECMAScript规定如果返回的是一个promise,会额外产生一个微任务来延迟执行。
也就是说
- 输出0以后, 返回了
Promise.resolve(4),这里产生了一个微任务,会把这一行放到一个新的微任务队列里面去。后面的console.log(res)会等待在Promise.resolve(4)后面执行。 - 然后执行
1,2,3, 这里第三个之后就会切换到另一个微任务,也就是第一个Promise的微任务继续执行。 - 然后就会执行到
console.log(res), 4.然后再依次往后面执行打印。
所以才会输出上面的0-6依次打印