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

Node.js事件循环中微任务执行位置及阶段优先级问询

Node.js事件循环与微任务优先级疑问

这是Node事件循环:

┌───────────────────────────┐
┌─>│           timers          │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │     pending callbacks     │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │       idle, prepare       │
│  └─────────────┬─────────────┘      ┌───────────────┐
│  ┌─────────────┴─────────────┐      │   incoming:   │
│  │           poll            │<─────┤  connections, │
│  └─────────────┬─────────────┘      │   data, etc.  │
│  ┌─────────────┴─────────────┐      └───────────────┘
│  │           check           │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
└──┤      close callbacks      │
   └───────────────────────────┘

我了解Node采用V8 JS引擎,且V8拥有可被嵌入者替换或扩展的自有事件循环。例如在Chrome中存在macrotask和microtask队列(microtask队列优先级高于macrotask队列),主线程调用栈为空时事件循环会从这些队列推送回调。

可通过queueMicrotask函数手动将微任务加入microtask队列,我在Node中测试该函数可正常运行。

我编写了如下代码测试Node事件循环的优先级:

const hello_world =() => {
    console.log("Hello World 2");
};

queueMicrotask(hello_world);

setTimeout(
    () => {
        console.log("Hello World 3");
    },
    0
);

console.log("Hello World 1");

/*
OUTPUT:

Hello World 1
Hello World 2
Hello World 3
*/

从输出可知微任务优先级高于timers(在Chrome事件循环中属于macrotask),但我有两个疑问:

  1. 在Node事件循环中,微任务被入队到哪个阶段?是否有专属阶段还是与其他回调混合?
  2. Node事件循环的各阶段优先级顺序是怎样的?

问题解答

1. Node.js中微任务的处理时机

Node.js里并没有为微任务划分独立的事件循环阶段,而是在每个事件循环阶段执行完毕后,都会清空所有微任务队列(包括queueMicrotask、process.nextTick、Promise回调等),再进入下一个阶段。

需要注意的是,process.nextTick的优先级比普通微任务(比如queueMicrotask、Promise.then)更高,会在其他微任务之前被执行,但它们都属于同一类需要在阶段间隙处理的任务。

2. Node.js事件循环各阶段的优先级顺序

Node.js事件循环的阶段严格按照以下顺序依次执行,每个阶段会先处理完该阶段所有可执行的回调,再处理微任务队列,然后进入下一个阶段:

  • timers:执行setTimeout、setInterval的到期回调
  • pending callbacks:处理系统操作的回调(比如TCP错误回调)
  • idle, prepare:仅内部使用,用户代码不会涉及
  • poll:检索新的I/O事件;执行与I/O相关的回调;如果没有待处理的回调,会在此阶段等待新的事件触发
  • check:执行setImmediate的回调
  • close callbacks:执行关闭相关的回调(比如socket.on('close', ...))

另外,每次事件循环启动时,会先执行所有process.nextTick队列中的任务,再开始进入上述阶段。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 16:09:27