面试题答案
一键面试宏任务队列常见任务类型
- I/O 操作:例如文件系统操作(如
fs.readFile
)、网络请求(如http.request
)等。Node.js 底层通过线程池或其他异步 I/O 机制来处理这些操作,操作完成后将对应的回调放入宏任务队列。 - setTimeout 和 setInterval:这两个函数设置的回调会被放入宏任务队列。它们按照设定的延迟时间,到期后将回调加入队列。例如
setTimeout(() => { console.log('timeout callback'); }, 1000);
,1 秒后其回调会被放入宏任务队列。 - setImmediate:它用于在当前轮询阶段结束时,将回调排入宏任务队列。与
setTimeout
不同,setImmediate
的回调总是在setTimeout
(延迟为 0)的回调之后执行,因为setTimeout
在进入事件循环前有最小延迟(约 4 毫秒),而setImmediate
直接在轮询阶段结束时执行。
微任务队列常见任务类型
- Promise 的回调:当一个 Promise 被解决(
resolve
)或被拒绝(reject
)时,.then
或.catch
中注册的回调会被放入微任务队列。例如Promise.resolve().then(() => { console.log('promise callback'); });
,此回调会被放入微任务队列。 - process.nextTick:这是 Node.js 特有的微任务,它的优先级比 Promise 的微任务更高。每次事件循环的轮询阶段准备进入下一个阶段前,会先处理
process.nextTick
队列中的所有任务,处理完process.nextTick
队列后,才会处理 Promise 微任务队列。
执行顺序
- 事件循环开始:进入事件循环,从宏任务队列中取出一个宏任务执行。
- 执行宏任务:执行过程中可能产生新的宏任务或微任务。例如在执行
fs.readFile
回调(宏任务)时,如果有Promise.resolve().then
,则会产生微任务。 - 处理微任务:宏任务执行完毕后,会清空微任务队列,即依次执行微任务队列中的所有任务。先执行
process.nextTick
队列中的任务,再执行 Promise 微任务队列中的任务。 - 进入下一轮事件循环:微任务队列清空后,事件循环进入下一轮,从宏任务队列中取出下一个宏任务执行,如此循环。