侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论

浏览器事件循环机制解析与宏任务/微任务执行顺序

2025-12-11 / 0 评论 / 3 阅读

题目

浏览器事件循环机制解析与宏任务/微任务执行顺序

信息

  • 类型:问答
  • 难度:⭐⭐

考点

事件循环原理,宏任务与微任务区别,异步代码执行顺序

快速回答

事件循环是浏览器处理异步任务的核心机制,其执行顺序为:

  1. 执行同步代码(调用栈清空)
  2. 执行所有微任务(如Promise)
  3. 执行一个宏任务(如setTimeout)
  4. 重复步骤2-3

关键区别:

  • 宏任务:setTimeout, setInterval, I/O, UI渲染
  • 微任务:Promise.then, MutationObserver, queueMicrotask
## 解析

1. 事件循环原理

浏览器采用单线程执行JavaScript,通过事件循环处理异步操作。核心组件:

  • 调用栈(Call Stack):同步代码执行栈
  • 任务队列(Task Queue):宏任务队列
  • 微任务队列(Microtask Queue):优先级更高的异步队列
  • 事件循环线程:持续检查调用栈和队列

2. 执行顺序示例

console.log('1'); // 同步

setTimeout(() => console.log('2'), 0); // 宏任务

Promise.resolve().then(() => {
  console.log('3'); // 微任务
  setTimeout(() => console.log('4'), 0); // 嵌套宏任务
});

console.log('5'); // 同步

// 输出顺序:1 → 5 → 3 → 2 → 4

3. 执行流程详解

  1. 同步代码执行:输出1和5
  2. 清空微任务队列:Promise.then回调输出3,同时注册新宏任务
  3. 执行一个宏任务:第一个setTimeout输出2
  4. 再次清空微任务队列(此时为空)
  5. 执行下一个宏任务:嵌套setTimeout输出4

4. 宏任务与微任务对比

特性宏任务(macrotask)微任务(microtask)
常见APIsetTimeout, setInterval, I/O, UI渲染Promise.then/catch/finally, MutationObserver, queueMicrotask
队列机制多个独立队列(定时器/I/O等)单个高优先级队列
执行时机每次循环取一个任务每轮循环全部清空

5. 最佳实践

  • 耗时操作用宏任务避免阻塞渲染
  • 关联异步操作使用Promise链保证执行顺序
  • 避免微任务嵌套过深导致饥饿(如递归添加微任务)
  • UI更新优先使用requestAnimationFrame

6. 常见错误

  • 误以为setTimeout(0)会立即执行(实际有最小延迟4ms)
  • 在微任务中同步修改DOM导致布局抖动
  • 忽略async/await本质是微任务包装
  • 宏任务中错误处理未用Promise.catch捕获

7. 扩展知识

  • requestAnimationFrame:在渲染前执行,适合动画
  • Web Workers:解决CPU密集型任务阻塞主线程
  • Node.js事件循环:额外包含process.nextTick和setImmediate
  • 性能影响:微任务过多会延迟渲染(如无限Promise递归)