一道关于事件循环(Event Loop) 机制和任务队列模型的面试题


​代码示例​

javascript 复制代码
console.log(1);
Promise.resolve().then(res => console.log(2));
setTimeout(() => console.log(3), 0);

​执行顺序​

​输出结果:1 → 2 → 3


​原理分析​

1. ​​同步任务优先执行​

  • console.log(1) 是同步任务,直接进入主线程执行,输出 1
  • Promise.resolve() 的构造函数是同步执行的,但 .then() 的回调会被注册为微任务(Microtask)。

2. ​​微任务队列(Microtask Queue)​

  • .then(res => console.log(2)) 的回调被放入微任务队列。
  • ​微任务优先级高于宏任务​:在当前同步任务执行完毕后,事件循环会优先清空微任务队列。

3. ​​宏任务队列(Macrotask Queue)​

  • setTimeout 的回调被放入宏任务队列。
  • 宏任务需等待当前所有微任务执行完毕后才会执行。

4. ​​事件循环流程​

  1. ​执行同步任务​ ​:输出 1

  2. ​注册微任务​ ​:将 .then 回调加入微任务队列。

  3. ​注册宏任务​ ​:将 setTimeout 回调加入宏任务队列。

  4. ​同步任务结束​​,开始处理微任务队列:

    • 执行 .then 回调,输出 2
  5. ​微任务队列清空​​,开始处理宏任务队列:

    • 执行 setTimeout 回调,输出 3

​关键概念​

1. ​​任务队列分类​

任务类型 示例 优先级
​同步任务​ console.log 最高
​微任务​ Promise.then 次高(当前轮次)
​宏任务​ setTimeout/setInterval 最低(下一轮次)

2. ​​事件循环核心规则​

  • ​同步任务​:立即执行,阻塞后续代码。
  • ​微任务​ :在 ​当前宏任务结束后、下一个宏任务开始前​ 执行。
  • ​宏任务​:每次事件循环仅执行一个,由任务队列顺序决定。

​浏览器与 Node.js 的差异​

  • ​浏览器环境​:微任务在 DOM 渲染前执行。
  • ​Node.js​ :微任务在 process.nextTick 之后、setImmediate 之前执行。

​复杂场景扩展​

若代码改为:

javascript 复制代码
console.log(1);
setTimeout(() => {
  console.log(2);
  Promise.resolve().then(() => console.log(3));
}, 0);
Promise.resolve().then(() => console.log(4));

​输出顺序:1 → 4 → 2 → 3

​原因​​:

  1. 同步任务输出 1
  2. 注册 setTimeout(宏任务)和 Promise.then(微任务)。
  3. 同步任务结束后,先执行微任务输出 4
  4. 执行宏任务 setTimeout,输出 2,其回调中的 Promise.then 又注册一个微任务,输出 3

​总结​

  • ​同步任务​:直接执行,无延迟。
  • ​微任务​:在当前事件循环末尾执行(如 Promise 回调)。
  • ​宏任务​:在下一次事件循环开始时执行(如 setTimeout)。

理解这一机制,能精准掌握异步代码的执行顺序,避免常见的回调地狱问题。

相关推荐
Aniugel8 小时前
单点登录(SSO)系统
前端
鹏多多8 小时前
移动端H5项目,还需要react-fastclick解决300ms点击延迟吗?
前端·javascript·react.js
serioyaoyao8 小时前
上万级文件一起可视化,怎么办?答案是基于 ParaView 的远程可视化
前端
万少8 小时前
端云一体 一天开发的元服务-奇趣故事匣经验分享
前端·ai编程·harmonyos
WindrunnerMax8 小时前
从零实现富文本编辑器#11-Immutable状态维护与增量渲染
前端·架构·前端框架
不想秃头的程序员8 小时前
Vue3 封装 Axios 实战:从基础到生产级,新手也能秒上手
前端·javascript·面试
数研小生8 小时前
亚马逊商品列表API详解
前端·数据库·python·pandas
你听得到118 小时前
我彻底搞懂了 SSE,原来流式响应效果还能这么玩的?(附 JS/Dart 双端实战)
前端·面试·github
不倒翁玩偶8 小时前
npm : 无法将“npm”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。
前端·npm·node.js