在 JavaScript 的异步编程模型中,宏任务(Macro Task)和微任务(Micro Task)是事件循环(Event Loop)机制中的两个重要概念。它们用于管理异步操作的执行顺序。
1. 宏任务 (Macro Task)
宏任务是较大的任务块,它们在事件循环的每一轮迭代中按顺序执行。常见的宏任务包括:
- setTimeout 和 setInterval
- setImmediate (Node.js 环境)
- I/O 操作
- UI 渲染
宏任务的执行流程
- 每次事件循环从宏任务队列中取出一个任务执行。
- 当一个宏任务执行完后,会检查微任务队列是否为空,如果不为空,优先执行所有微任务队列中的任务。
- 之后,事件循环继续进入下一个宏任务。
2. 微任务 (Micro Task)
微任务是更细粒度的任务,比宏任务优先级更高。微任务会在当前宏任务执行完后立即执行,并在下一个宏任务开始之前完成。
常见的微任务包括:
- Promise.then/catch/finally
- MutationObserver
- queueMicrotask
微任务的执行流程
- 当前宏任务执行完毕后,立即执行所有的微任务,直到微任务队列为空。
- 新增的微任务会被加入当前微任务队列,直到所有微任务都完成。
宏任务和微任务的区别
特性 | 宏任务 (Macro Task) | 微任务 (Micro Task) |
---|---|---|
优先级 | 优先级低,执行顺序在微任务之后 | 优先级高,当前宏任务执行后立即执行 |
典型场景 | setTimeout、setInterval、I/O、UI 渲染等 | Promise.then、queueMicrotask 等 |
执行时机 | 每次事件循环的起始阶段 | 当前宏任务完成后,下一个宏任务之前 |
实际示例
以下代码展示了宏任务和微任务的执行顺序:
console.log('开始'); // 同步任务
setTimeout(() => {
console.log('宏任务:setTimeout');
}, 0);
Promise.resolve().then(() => {
console.log('微任务:Promise');
});
console.log('结束'); // 同步任务
执行顺序:
- 同步任务:输出
'开始'
- 同步任务:输出
'结束'
- 微任务:输出
'微任务:Promise'
- 宏任务:输出
'宏任务:setTimeout'
图解事件循环
- 同步任务直接进入主线程执行。
- 微任务进入微任务队列。
- 宏任务进入宏任务队列。
事件循环的顺序为:
- 执行主线程的同步代码。
- 清空微任务队列。
- 执行一个宏任务(从宏任务队列中取出)。
- 回到第二步,重复以上流程。
关键点总结
- 微任务优先级高于宏任务。
- 微任务适用于需要尽快执行的逻辑(如 Promise 的回调)。
- 宏任务适用于稍后执行的逻辑(如计时器或 I/O 操作)。
了解这些机制,可以帮助我们更好地调试和优化 JavaScript 代码的异步行为。