2025-05-21 08:58

JavaScript宏任务与微任务解析

王姐姐

WEB前端

(33)

(0)

收藏

1. 定义与常见类型

  • 宏任务

    • 代表较大的、离散的工作单元。

    • 常见类型:setTimeoutsetInterval、I/O操作(如文件读取)、UI渲染、整体脚本(<script>)的执行。

  • 微任务

    • 代表需要尽快执行的小任务,通常与当前宏任务相关。

    • 常见类型:Promise的回调(then/catch/finally)、MutationObserverprocess.nextTick(Node.js 环境)。


2. 执行顺序

事件循环按以下步骤运行:

  1. 执行一个宏任务(如初始脚本或setTimeout回调)。

  2. 执行所有微任务:当前宏任务结束后,依次执行微任务队列中的所有任务(包括执行过程中新添加的微任务)。

  3. UI渲染(如果需要):浏览器可能在此阶段更新视图。

  4. 重复循环:取下一个宏任务执行,依此类推。


3. 关键规则

  • 微任务优先:每个宏任务执行完毕后,必须清空微任务队列,才能执行下一个宏任务。

  • 微任务递归执行:若微任务中产生新的微任务,这些新任务会继续在当前阶段执行,直到队列为空。

  • 宏任务按队列顺序执行:新宏任务会被添加到队列末尾,依次处理。


4. 示例分析

示例 1:基础顺序

console.log("start");

setTimeout(() => console.log("setTimeout"), 0);

Promise.resolve().then(() => console.log("promise"));

console.log("end");

输出start → end → promise → setTimeout
解析

  • 主脚本(宏任务)执行,输出startend

  • 微任务队列中的Promise回调先于setTimeout执行。


示例 2:微任务嵌套

Promise.resolve().then(() => {
  console.log("微任务1");
  Promise.resolve().then(() => console.log("微任务2"));
});

输出微任务1 → 微任务2
解析:微任务中产生的新微任务会在当前阶段立即执行。


示例 3:混合宏任务与微任务

setTimeout(() => {
  console.log("宏任务1");
  Promise.resolve().then(() => console.log("微任务1"));
}, 0);

setTimeout(() => {
  console.log("宏任务2");
  Promise.resolve().then(() => console.log("微任务2"));
}, 0);

输出宏任务1 → 微任务1 → 宏任务2 → 微任务2
解析:每个宏任务结束后,立即处理其产生的微任务。


5. 注意事项

  • 避免微任务无限循环:在微任务中递归添加微任务会导致阻塞,阻碍后续宏任务执行。

  • Node.js 的差异process.nextTick的优先级高于Promise,属于微任务中的特例。

  • UI渲染的时机:频繁的微任务可能延迟渲染,影响页面性能。


总结

  • 宏任务:离散的异步任务,按队列顺序执行。

  • 微任务:高优先级的任务,在宏任务结束后立即执行,确保快速响应。

  • 事件循环:通过交替执行宏任务和清空微任务队列,实现高效异步处理。

理解两者的区别与执行顺序,能帮助开发者优化代码性能,避免异步逻辑中的意外行为。


0条评论

点击登录参与评论