← [ BACK_TO_NOTES ]

Node.js 事件循环阶段

解释现代 Node.js/libuv 的 phases、poll/check/timers 职责,以及 process.nextTick 与 V8 microtasks 的配合方式。

#concept #evergreen #backend #nodejs #javascript

[!info] related notes

Node.js 事件循环阶段

一句话定义

Node.js Event Loop 由 libuv 驱动,不应只用“宏任务 / 微任务”理解;它由 I/O phases 配合 process.nextTick 和 V8 microtasks 调度 JavaScript。

Node 默认只有一条 JavaScript 执行主线,但整个 Runtime 不是单线程:大量网络 I/O 由操作系统处理,部分文件、DNS、crypto 等工作还会使用 libuv Worker Pool。

核心 phases

现代 Node.js 可以重点理解:

pending callbacks
→ idle / prepare
→ poll
→ check
→ close callbacks
→ timers
→ 下一轮

Node.js 20 / libuv 1.45 起,正常 event-loop iteration 中 timers 在 poll 之后运行;早期资料常画成 timers 在 poll 之前。

pending callbacks

处理部分延迟到下一轮的系统级 I/O callbacks,例如某些 TCP error callbacks。

idle / prepare

libuv / Node 内部使用,业务代码通常不直接关心。

poll

最关键的 phase 之一:计算等待 I/O 的时长、获取新 I/O events、执行 poll queue 中的大部分 callbacks。

check

执行 setImmediate(callback)。check 不负责 close callback。

close callbacks

执行部分资源关闭回调,例如 socket.on('close', callback)。

timers

执行达到时间阈值的 setTimeout / setInterval callbacks。delay 是最小阈值,不保证到点立刻执行。

nextTick 与 V8 microtasks

当前 JavaScript callback / operation 完成
→ process.nextTick queue
→ V8 microtasks
   ├─ Promise.then / catch / finally
   └─ queueMicrotask
→ 继续 Event Loop phase

因此通常:

Promise.resolve().then(() => console.log('promise'))
process.nextTick(() => console.log('nextTick'))

输出:

nextTick
promise

递归注册 nextTick 会造成 starvation,使 timer 和 I/O 长时间无法运行。

setImmediate 与 setTimeout(0)

顶层代码里不要背死顺序,实际取决于运行位置和 timer 是否达到阈值。在 I/O callback 中,当前从 poll 处理完 I/O 后通常进入 check,所以 setImmediate 更容易先于新建的 timer 执行。

学习检查

不看正文回答:

  1. Node.js Event Loop 为什么不能只用“宏任务 / 微任务”两类解释?
  2. poll、check、timers、close callbacks 分别负责什么?
  3. process.nextTick 为什么不属于 libuv phase?
  4. nextTick 与 V8 microtasks 在当前 JavaScript callback 返回后如何排序?
  5. 为什么 setImmediate 与 setTimeout(0) 在顶层代码里不能死背固定顺序?
  6. 递归 nextTick 为什么可能让 I/O 或 timer starvation?
  7. 给一段在 I/O callback 内同时安排 nextTick、Promise、setImmediate、setTimeout 的代码,先写出调度层级再预测输出。
创建于 2026/5/21 更新于 2026/9/30
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本