Skip to content

异步与事件循环

Node.js 以单个 JavaScript 主线程执行回调。I/O 完成、定时器到期等事件由事件循环调度;并不意味着所有工作都在单线程完成。

执行顺序

一次 JavaScript 调用栈清空后,Node.js 会先清空微任务,再进入下一轮事件循环:

  1. process.nextTick() 队列。
  2. Promise 微任务队列(queueMicrotaskPromise.then)。
  3. 事件循环阶段中的任务,例如定时器、I/O 回调、setImmediate()

process.nextTick() 优先级很高;递归排入会饿死 I/O,应仅用于兼容或确有必要的延后执行。普通异步编排优先使用 Promise 或 queueMicrotask()

js
setTimeout(() => console.log('timeout'), 0)
setImmediate(() => console.log('immediate'))
Promise.resolve().then(() => console.log('promise'))
process.nextTick(() => console.log('nextTick'))

// 固定顺序:nextTick -> promise
// timeout 与 immediate 的相对顺序取决于调用位置与运行时状态。

setTimeoutsetImmediate

  • setTimeout(fn, 0):在定时器阈值到达后执行,不保证立刻执行。
  • setImmediate(fn):在 I/O 轮询后、check 阶段执行。
  • 在 I/O 回调内部,setImmediate 通常先于 setTimeout(0)

阻塞风险

以下操作会占用主线程并延迟所有请求:同步 fs API、复杂正则、巨型 JSON 的同步解析、大循环和 CPU 密集加密/压缩。请求路径应保持短小;耗时任务改为分批、工作线程或队列任务。

基于 MIT 许可发布