process.nexttick 不属于标准微任务队列,而是由 node.js 单独维护 nexttickqueue,在每个事件循环阶段结束前立即清空,早于 promise.then 等 v8 微任务执行。

因为 process.nextTick 根本不走标准微任务队列,而是由 Node.js 运行时单独维护一个 nextTickQueue,在每个事件循环阶段结束前强制清空——这个动作发生在 V8 执行 Promise.then、queueMicrotask 等标准微任务之前。
它不是“微任务里排第一”,而是“根本不进那个队列”
很多人误以为 nextTick 是“最高优先级的微任务”,其实它和 Promise 微任务分属两套调度系统:
- V8 引擎只管自己的微任务队列(Promise、queueMicrotask、MutationObserver),并在宏任务结束后统一执行;
- Node.js 自己维护
nextTickQueue,完全绕开 V8 的微任务调度机制; - 每次 timers、I/O、check 等任一阶段执行完回调后,Node.js 就立刻清空 nextTick 队列,然后才进入下一阶段或交还控制权给 V8。
执行时机比 Promise.then 更早,是硬性顺序
看这段代码输出就非常清楚:
console.log('start');
process.nextTick(() => console.log('nextTick'));
Promise.resolve().then(() => console.log('promise'));
console.log('end');
结果恒为:start → end → nextTick → promise。这说明:
- 同步代码(start、end)先跑完;
- 紧接着立即执行所有 pending 的 nextTick 回调;
- 等 nextTick 队列彻底清空后,V8 才开始处理微任务队列里的 Promise.then。
它能插队,还能连续串行执行
哪怕你在 Promise.then 里调用 process.nextTick,新回调也不会等到下一轮,而是塞进当前阶段的 nextTick 队列尾部,仍会在本轮该阶段结束时执行:
- 连续调用 5 次
process.nextTick,它们会一个接一个执行,中间不会插入任何 Promise.then、I/O 或定时器回调; - 即使
setImmediate写在process.nextTick前面,执行顺序仍是 nextTick 先——这不是竞态,是事件循环阶段设计决定的硬性顺序。
本质是“当前 tick 尾部的最后干预机会”
它的设计初衷不是为了抢微任务的风头,而是提供一个极细粒度的控制点:
- 用于错误边界处理(比如在回调中抛错前确保 error 事件被监听);
- 保持 API 同步/异步行为一致(避免用户代码因条件分支导致同步或异步执行不统一);
- 分解长同步任务,防止阻塞但又不想退到下一轮事件循环(比如避免 setTimeout(0) 带来的延迟不确定性)。











