CodeWalk

Node.js 事件循环和浏览器事件循环有什么区别?

作者:我还是少年 · 2026-05-30 12:55

请比较 Node.js 和浏览器中事件循环机制的差异,特别是 process.nextTick 的作用。

回答

我还是少年

浏览器事件循环

  • 宏任务 → 清空微任务 → 渲染(requestAnimationFrame)→ 下一个宏任务
  • 任务队列相对简单

Node.js 事件循环(libuv):基于 phases 的阶段模型

  1. timers:执行 setTimeout/setInterval 回调
  2. pending callbacks:执行延迟到下一轮的 I/O 回调
  3. idle, prepare:内部使用
  4. poll:获取新的 I/O 事件;若无定时器超时则阻塞等待
  5. check:setImmediate 回调
  6. close callbacks:关闭事件回调(如 socket 关闭)

process.nextTick 的特殊性

  • 不属于任何 phase,在当前 phase 结束后、下一 phase 前立即执行
  • 优先级高于微任务队列
  • 递归调用可能导致 I/O starvation,Node.js 有 maxListeners 限制

执行顺序(Node.js):

process.nextTick(() => console.log('nextTick'));
Promise.resolve().then(() => console.log('promise'));
// Node 旧版:nextTick → promise
// Node 11+ 行为调整后:nextTick → promise(但 phases 边界处理更复杂)

主要差异表: | 特性 | 浏览器 | Node.js | |------|--------|--------| | 任务队列模型 | 宏任务+微任务 | phases 模型 | | process.nextTick | 无 | 有,优先于微任务 | | setImmediate | 无 | 有,check phase 执行 | | requestAnimationFrame | 有 | 无 | | UI 渲染 | 宏任务后 | 无 UI |