Node.js v10.15.0中Promise执行顺序异常问题咨询
为什么Node.js v10中Promise链的输出顺序和预期不符?
这是因为你误解了Node.js中**微任务队列(microtask queue)的执行机制。Promise的then回调属于微任务,而微任务队列的处理是先进先出(FIFO)**的,并不会优先处理同一个Promise链的后续回调。
让我们一步步拆解代码的执行流程:
1. 同步代码执行阶段
首先,同步执行所有非异步代码:
- 调用
Promise.resolve(),将第一个then的回调(console.log('A'))添加到微任务队列。 - 调用
setImmediate(...),将其回调添加到**宏任务队列(macrotask queue)**的check阶段(setImmediate属于这个阶段)。 - 调用第二个
Promise.resolve(),将它的第一个then回调(console.log('D'))添加到微任务队列。
此时,微任务队列里的顺序是:[log A, log D],宏任务队列里是[log IMMEDIATE]。
2. 微任务队列处理阶段
同步代码执行完毕后,Node.js会先清空所有微任务(直到队列空为止),处理流程如下:
- 取出队列第一个任务:执行
log A。执行完后,这个Promise的第二个then回调(log B)被添加到微任务队列。此时队列变为[log D, log B]。 - 取出下一个任务:执行
log D。执行完后,第二个Promise的第二个then回调(log E)被添加到微任务队列。此时队列变为[log B, log E]。 - 取出下一个任务:执行
log B。执行完后,第一个Promise的第三个then回调(log C)被添加到微任务队列。此时队列变为[log E, log C]。 - 取出下一个任务:执行
log E。执行完后,第二个Promise的第三个then回调(log F)被添加到微任务队列。此时队列变为[log C, log F]。 - 取出下一个任务:执行
log C,没有后续then,队列变为[log F]。 - 取出最后一个任务:执行
log F,微任务队列清空。
3. 宏任务队列处理阶段
微任务全部处理完后,Node.js才会处理宏任务队列,执行setImmediate的回调,输出IMMEDIATE。
关键误区
你预期第一个Promise链(A→B→C)完全执行完再处理第二个链(D→E→F),但实际上,每个then回调执行后新增的微任务,会被追加到队列尾部,而队列里已经存在第二个Promise的第一个回调,所以会优先执行它,而不是当前链的下一个回调。微任务队列不区分属于哪个Promise链,只按加入顺序执行。
另外补充:setImmediate确实是推迟到下一轮事件循环(宏任务阶段),但它的执行是在所有微任务之后,这部分你的理解是对的,输出顺序里它在最后也验证了这一点。
内容的提问来源于stack exchange,提问作者pragmaticus
相关产品推荐
相关产品推荐

