首先我们需要了解的是:如果有多个fulfilled promise实例,同时执行then链式调用:then会交替执行。这是编译器的优化,防止一个promise占据太久时间。
then中返回一个promise实例,相当于多出一个promise实例,也会遵守交替执行(但和直接声明一个promise实例,结果有些差异的)
then中返回promise实例,会出现“慢两拍”的效果原因如下
第一拍:promise需要由pending变为fulfilled
第二拍:then函数挂载到微任务队列
看一个例子
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)
})
// 打印结果是什么
假如第3行代码返回return 4,代码则正常交替执行
结果依次输出为:0, 1, 4, 2, 3, 5, 6
但是如果返回的是一个promise呢,上面代码输出结果是什么呢?
结果为:0, 1, 2, 3, 4, 5, 6
从结果上看,如果正常交替执行的话,第一个promise为什么会慢两拍才输出4呢?
详细过程如下:
首先执行第1行,promise直接执行,然后遇到then,挂载到微任务队列;【then 0】
然后执行第8行,promise直接执行,然后遇到then,挂载到微任务队列;【then 0,then 1】
然后同步代码执行完毕,开始执行微任务队列中的任务。
首先执行promiseA的then输出0。【then 1】
然后发现有个return,这时候不管是执行完函数内容,或者提前return了,都先不理会,将后续内容挂载到微任务队列。【then 1, return...】
然后执行promiseB的then输出1,发现后面没内容了,将后续内容挂载到微任务队列。【return...,then2】
这时候又到promiseA了,发现返回的是一个新的promise。需要新的promise来决断是成功还是失败。
决断这一步也是跟then同理,需要交替执行,因此这一步执行完就又改promiseB执行了【then2, resolve(4)】
然后promiseB执行then输出2,将后续内容挂载到微任务队列【resolve(4),then(3)】
这时候又到promiseA了,发现刚刚决断完的promise是成功的,需要执行成功方法,也就相当于执行一个then。而then需要挂载到微任务队列【then(3), then(res)】
然后promiseB执行then输出3,将后续内容挂载到微任务队列【then(res), then(5)】
这时候又到promiseA了,这时候就直接输出then(res),也就是输出4。promiseA执行完了,如果还有then的话,继续添加到微任务中【then(5)】
然后promiseB执行then输出5,将后续内容挂载到微任务队列【then(6)】
然后promiseB执行then输出6,promiseB执行完毕