宏任务和微任务

宏任务和微任务:深入理解 JavaScript 的事件循环机制

1. 什么是事件循环?

JavaScript 是单线程语言,但它通过 事件循环(Event Loop) 实现了异步操作。事件循环是 JavaScript 运行时环境的核心机制,负责调度和执行任务。


2. 任务队列

在事件循环中,任务被分为两种类型:

  • 宏任务(Macro Task):较大的任务单元,如 setTimeoutsetIntervalI/O 操作等。
  • 微任务(Micro Task):较小的任务单元,如 PromiseMutationObserver 等。

3. 事件循环的执行顺序

事件循环的执行顺序如下:

  1. 执行一个宏任务(从宏任务队列中取出一个任务执行)。
  2. 执行所有微任务(清空微任务队列)。
  3. 更新渲染(如果需要)。
  4. 重复上述步骤

4. 宏任务和微任务的来源

4.1 宏任务

  • **setTimeoutsetInterval**:定时器任务。
  • I/O 操作:如文件读写、网络请求等。
  • UI 渲染:浏览器渲染任务。
  • script 标签:整个脚本的执行也是一个宏任务。

4.2 微任务

  • **Promise**:Promise 的回调(thencatchfinally)。
  • **MutationObserver**:DOM 变化的回调。
  • **process.nextTick**(Node.js):Node.js 中的微任务。

5. 示例分析

5.1 示例代码

1
2
3
4
5
6
7
8
9
10
11
console.log('script start');

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

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

console.log('script end');

5.2 执行顺序

  1. 执行宏任务script 标签(整个脚本)。
    • 输出:script start
    • 输出:script end
  2. 执行微任务Promise 的回调。
    • 输出:promise
  3. 执行下一个宏任务setTimeout 的回调。
    • 输出:setTimeout

最终输出顺序:

1
2
3
4
script start
script end
promise
setTimeout

6. 宏任务和微任务的区别

特性 宏任务(Macro Task) 微任务(Micro Task)
任务类型 较大的任务单元 较小的任务单元
执行顺序 在事件循环的每个周期执行一个宏任务 在每个宏任务执行后,清空微任务队列
常见来源 setTimeoutsetIntervalI/O 操作 PromiseMutationObserver
优先级 较低 较高

7. 实际应用

7.1 避免阻塞渲染

由于微任务会在渲染之前执行,因此可以将高优先级的任务放在微任务中,避免阻塞渲染。

7.2 优化性能

通过合理使用宏任务和微任务,可以优化 JavaScript 的执行性能。例如,将多个小任务合并为一个微任务,减少事件循环的负担。


8. 总结

宏任务和微任务是 JavaScript 事件循环的核心概念。理解它们的执行顺序和区别,有助于我们编写更高效、更可靠的代码。

希望这篇文章对你理解宏任务和微任务有所帮助!如果有任何问题或建议,欢迎随时联系我! 😊