Promise链式调用中microtasks queue任务顺序疑问
我不理解任务被送入microtasks queue的顺序。我预期的输出为:1, 11, 111, 2, 3, 12, 122,但实际得到的输出是:1, 11, 111, 2, 12, 122, 3。请问编译器是会注册整个Promise链,还是仅能识别下一个then?这一机制具体是如何运作的?
对应的代码如下:
Promise.resolve() .then(() => console.log(1)) .then(() => console.log(2)) .then(() => console.log(3)); Promise.resolve() .then(() => console.log(11)) .then(() => console.log(12)); Promise.resolve() .then(() => console.log(111)) .then(() => console.log(122));
机制解释
首先明确:JavaScript引擎不会预先注册整个Promise链,每个then的回调只会在前一个Promise完成(决议)后,才会被添加到微任务队列中。具体执行流程如下:
初始微任务队列填充:
三个Promise.resolve()会立即进入已决议状态,它们的第一个then回调会按照代码书写顺序依次被加入微任务队列。此时队列顺序为:[输出1的回调, 输出11的回调, 输出111的回调]。第一轮微任务执行:
事件循环开始处理微任务队列,依次执行三个回调,输出1、11、111。链式回调的添加逻辑:
每个then执行完毕后,会返回一个新的已决议Promise(因为回调没有返回异步值),此时这个新Promise绑定的下一个then回调会被加入微任务队列:- 执行完
输出1的回调后,输出2的回调被加入队列; - 执行完
输出11的回调后,输出12的回调被加入队列; - 执行完
输出111的回调后,输出122的回调被加入队列;
此时微任务队列更新为:[输出2的回调, 输出12的回调, 输出122的回调]。
- 执行完
第二轮微任务执行:
依次执行队列中的回调,输出2、12、122。最后一个回调的添加与执行:
执行完输出2的回调后,它返回的新Promise会触发第三个then的输出3回调加入队列,此时队列中只有这个回调,执行后输出3。
这就是为什么实际输出顺序是1, 11, 111, 2, 12, 122, 3,而非你预期的顺序——你错误假设了整个Promise链的回调会被一次性加入队列,但实际上它们是在前一个步骤完成后才被逐步添加的。
内容的提问来源于stack exchange,提问作者Steven Steeve

