MST

星途 面试题库

面试题:Node.js事件循环中微任务和宏任务在六个阶段的执行时机

请阐述Node.js事件循环六个阶段中,微任务(microtask)和宏任务(macrotask)分别在哪些阶段执行,以及它们的执行顺序关系,并举例说明。
46.7万 热度难度
前端开发Node.js

知识考点

AI 面试

面试题答案

一键面试

Node.js事件循环六个阶段

  1. timers:本阶段执行 setTimeoutsetInterval 回调。
  2. pending callbacks:执行系统操作的回调,比如 TCP 连接错误等。
  3. idle, prepare:仅系统内部使用。
  4. poll:检索新的 I/O 事件;执行与 I/O 相关的回调(除了 close 事件,timers 回调,setImmediate 回调)。如果没有 setImmediate 等任务,会在此阶段阻塞等待新的 I/O 事件。
  5. check:执行 setImmediate 回调。
  6. close callbacks:执行 close 事件回调,例如 socket.on('close', ...)

微任务和宏任务执行位置及顺序

  • 宏任务
    • timers 阶段执行 setTimeoutsetInterval 的回调。
    • pending callbacks 阶段执行特定系统操作回调。
    • poll 阶段执行大部分 I/O 相关回调。
    • check 阶段执行 setImmediate 回调。
    • close callbacks 阶段执行 close 事件回调。
  • 微任务
    • 每个宏任务执行完毕后,在进入下一个宏任务之前,会先执行微任务队列中的所有任务。微任务通常包括 process.nextTick(Node.js 独有的,它的优先级高于其他微任务),Promise.thenMutationObserver(浏览器环境中有,Node.js 中没有直接关联)等。

执行顺序关系

  1. 事件循环从一个阶段到下一个阶段前,会先清空微任务队列。
  2. 微任务队列始终优先于宏任务队列执行。

举例说明

setTimeout(() => {
  console.log('setTimeout callback');
}, 0);

Promise.resolve().then(() => {
  console.log('Promise.then callback');
});

process.nextTick(() => {
  console.log('process.nextTick callback');
});

// 输出顺序:
// process.nextTick callback
// Promise.then callback
// setTimeout callback

在这段代码中,process.nextTick 属于微任务且优先级高于 Promise.then,所以先输出 process.nextTick callback,然后 Promise.then 回调进入微任务队列也被执行,最后 setTimeout 属于宏任务,在当前宏任务(这里是主脚本执行完毕,可看作一个宏任务)结束,微任务队列清空后,在 timers 阶段被执行。