You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js事件循环:CJS与ESM中nextTick与Promise回调执行顺序为何反转?

CommonJS与ES模块中process.nextTick和Promise队列执行顺序差异解析

现象复现

CommonJS模块(index.js)

Promise.resolve().then(() => console.log("this is Promise.resolve 1"));
process.nextTick(() => console.log("this is process.nextTick 1"));

执行日志:

this is process.nextTick 1
this is Promise.resolve 1

ES模块(index.mjs)

Promise.resolve().then(() => console.log("this is Promise.resolve 1"));
process.nextTick(() => console.log("this is process.nextTick 1"));

执行日志:

this is Promise.resolve 1
this is process.nextTick 1

核心原因:模块加载阶段的队列初始化差异

Node.js处理不同模块类型时,模块初始化时机与微任务队列触发逻辑存在本质差异:

  • CommonJS模块执行逻辑
    CJS模块同步加载执行,模块代码运行时,process.nextTick和Promise.resolve().then的回调会分别加入nextTickQueue和PromiseJobs两个微任务队列。Node.js默认微任务优先级为nextTickQueue > PromiseJobs,模块代码执行完毕后会先清空nextTickQueue,再处理PromiseJobs,因此process.nextTick回调先执行。

  • ES模块执行逻辑
    ESM采用异步加载机制,Node.js会将模块的执行逻辑封装到一个Promise回调中触发。这意味着你在ESM模块中添加的Promise.resolve().then回调,和模块执行的外层Promise属于同一PromiseJobs队列批次;而process.nextTick的回调是在外层Promise之后才被加入nextTickQueue。当外层Promise执行时,会先处理同批次的PromiseJobs回调(即代码中的Promise回调),之后才会轮到nextTickQueue中的回调,最终呈现相反的执行顺序。

内容的提问来源于stack exchange,提问作者Vishwas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 22:47:26