Skip to content

Node 的事件循环和浏览器有什么不同? ​

Node 的主线程按阶段处理回调:定时器、挂起的回调、空闲、轮询、setImmediate、关闭回调。每个阶段结束后会去清微任务。process.nextTick 的队列比 Promise 的微任务更早。

原理 ​

setTimeout 在 timers 阶段。setImmediate 在 check 阶段,一般晚于当前轮询。在 I/O 回调里,setImmediate 往往先于 setTimeout(fn, 0)。在主模块里两者的先后不要依赖,启动时机不同结果会变。

process.nextTick 会在当前操作结束后立刻执行,并且可以再往这个队列里加任务。队列不空,事件循环进不了下一阶段,I/O 会被饿死。能用 Promise 就不要用 nextTick 去递归排队。

浏览器没有 setImmediate 和 nextTick。微任务仍然是 Promise。讲面试题时先问清运行环境,再画阶段。见 Event Loop。

追问 ​

同步代码会不会插进阶段中间?

当前 JavaScript 栈不空,事件循环不会取下一个回调。一个阶段里如果回调又同步做了很久的计算,后面的阶段都要等。

nextTick 和 queueMicrotask 谁先?

同一轮里先排空 nextTick,再排空 Promise 微任务。然后才能进入下一个事件循环阶段。

易错点 ​

  • 用浏览器那张「宏任务、微任务」图直接套 Node 的全部 API。
  • 在 nextTick 里继续 nextTick,接口不再接受连接。
  • 断言 setTimeout(0) 一定早于 setImmediate。

相关 ​