JavaScript中的宏任务(Macrotasks)和微任务(Microtasks)是管理异步代码执行顺序的两个重要概念,它们之间存在明显的区别。以下是它们的主要区别:
1. 调度时机和执行顺序
- 宏任务:宏任务是由浏览器提供的任务源,常见的宏任务包括
script
(整体代码)、setTimeout
、setInterval
、I/O操作、UI渲染等。宏任务会进入到宏任务队列中,当执行栈为空时,事件循环会从宏任务队列中选择一个任务来执行。每个宏任务之间会存在一个时间间隔,即宏任务之间会互相等待,直到前一个宏任务执行完毕。 - 微任务:微任务是在当前任务执行完毕后立即执行的任务,可以看作是在当前任务的末尾添加的任务,以确保在下一个事件循环之前执行。常见的微任务包括
Promise
的then
/catch
/finally
方法、MutationObserver
等。微任务会在当前宏任务执行结束后立即执行,而不需要等待下一个宏任务。
2. 优先级
- 微任务的优先级高于宏任务。当宏任务执行完毕后,会首先执行微任务队列中的任务,然后再执行下一个宏任务。
3. 来源
- 宏任务:宏任务来自于浏览器提供的任务源,如定时器、I/O操作等。
- 微任务:微任务是由一些特定的API触发的,如
Promise
、MutationObserver
等。
4. 生命周期和特性
- 宏任务:每个事件循环的开始处执行一个宏任务,执行过程中可能会产生新的微任务。宏任务之间会存在时间间隔,允许其他任务(如UI渲染)在宏任务之间执行。
- 微任务:在每个宏任务执行完毕后立即执行,直到微任务队列清空。微任务的执行可以产生新的微任务,这些新生成的微任务也会在当前事件循环迭代中执行。
5. 示例和执行顺序
假设有以下代码:
console.log('1');
setTimeout(() => {
console.log('2');
}, 0);
Promise.resolve().then(() => {
console.log('3');
});
console.log('4');
执行顺序将是:
1
4
3
2
解释:
- 首先执行同步代码,输出
1
和4
。 - 然后,
setTimeout
被推入宏任务队列,Promise.resolve().then()
的回调函数被推入微任务队列。 - 同步代码执行完毕后,开始执行微任务队列中的任务,输出
3
。 - 所有微任务执行完毕后,开始执行宏任务队列中的
setTimeout
,输出2
。
综上所述,宏任务和微任务在JavaScript中用于管理异步代码的执行顺序,它们之间的区别主要体现在调度时机、执行顺序、优先级、来源以及生命周期等方面。理解这些区别对于编写高效、可预测的异步JavaScript代码至关重要。