Node.js 的事件循环(Event Loop)是怎样的?宏任务与微任务的执行顺序?
Node.js 基于 libuv 实现事件循环,把回调按阶段(phase)依次执行,每个阶段有自己的 FIFO 队列:
┌───────────────────────┐
│ timers │ setInterval / setTimeout 回调
│ I/O callbacks │ 上一轮 I/O 的延迟回调(如 TCP 错误)
│ idle, prepare │ 内部使用
│ poll │ 取回新的 I/O 事件(文件/网络)
│ check │ setImmediate 回调
│ close callbacks │ close 事件(如 socket.destroy)
└───────────────────────┘微任务在两个节点之间、每个阶段切换前清空(全清空,不是只取一个):
process.nextTick队列:优先级最高,独立于微任务,会在每次阶段切换、甚至 I/O 之前执行Promise.then / queueMicrotask属于微任务
执行顺序口诀:同一圈里,先跑完当前阶段的宏任务队列 → 清空 nextTick 队列 → 清空微任务队列 → 进入下一阶段。
setTimeout(() => console.log('timeout'), 0)
setImmediate(() => console.log('immediate'))
Promise.resolve().then(() => console.log('promise'))
process.nextTick(() => console.log('nextTick'))
// 输出:nextTick → promise → (timeout 与 immediate 顺序不定,取决于事件循环启动耗时)注意:
setTimeout(fn,0)实际最小约 1ms;在主模块里setImmediate通常早于setTimeout,但在 I/O 回调内部则相反。