1. Node.js 事件循环的六个阶段(timers/pending/poll/check/close)与浏览器事件循环的差异?setImmediate 与 setTimeout(0) 的执行顺序为何不确定?
Node.js 事件循环的六个阶段(timers/pending/poll/check/close)是什么?与浏览器事件循环有何差异?setImmediate 与 setTimeout(0) 的执行顺序为何不确定?
- Node 事件循环的阶段模型(timers → pending → poll → check → close)
- 与浏览器事件循环(任务/微任务 + 渲染)的差异
- setImmediate 与 setTimeout(0) 顺序不确定的机制原因(阶段时序)
Node.js 事件循环分六个阶段:timers(执行 setTimeout/setInterval 到期回调)、pending(处理系统事件如 TCP 错误)、idle/prepare(内部)、poll(取新 I/O 事件、执行 I/O 回调;无任务时阻塞等待)、check(执行 setImmediate 回调)、close(close 事件回调),每阶段间执行"微任务(process.nextTick 优先、Promise 队列)";核心是"阶段轮转 + 微任务插队";浏览器事件循环是"任务队列(宏任务)+ 微任务队列"模型(每轮取一个宏任务 → 清空微任务 → 渲染检查),没有 poll 阶段的"I/O 轮询"概念(浏览器 I/O 是任务投递),且浏览器有渲染帧与 rAF 阶段、无 process.nextTick。
setImmediate 与 setTimeout(0) 顺序不确定的原因:setTimeout(0) 的回调进 timers 阶段、setImmediate 回调进 check 阶段,两者分属相邻阶段;在"主模块(非 I/O)"中执行时,事件循环从 timers 开始:若 setTimeout(0) 的定时器已到期则先执行 timers(setTimeout 先),若到期检查时未到期(或计时器阈值偏差),则先经历 poll 到 check(setImmediate 先)——取决于"定时器到期时刻与进入 timers 阶段的先后",受启动开销、计时器精度影响,故不确定;但在 I/O 回调(poll 阶段执行)中注册两者时,poll 之后必到 check(setImmediate 先于下一轮 timers)——顺序确定(setImmediate 先)。工程启示:需要确定顺序时用 process.nextTick(本阶段后立即)或显式编排,不依赖二者相对顺序。
本题考察事件循环的机制精度:六阶段模型、阶段间微任务、与浏览器的差异、setImmediate/setTimeout 的不确定性来源。回答应说明阶段流转与"定时器到期时序"这一不确定性根源。