在JavaScript中,宏任务(macro-task)和微任务(micro-task)是指异步操作的两种类型。
基本操作
宏任务通常包括以下操作:
- setTimeout和setInterval定时器回调函数
- 事件回调函数(例如,鼠标点击、键盘输入等)
- AJAX请求的回调函数
- 请求动画帧(requestAnimationFrame)回调函数
- script标签的onload和onerror事件
当一个宏任务开始执行时,JavaScript 引擎会将其放入调用堆栈的底部,然后继续执行其他代码。当调用堆栈为空时,JavaScript引擎会取出下一个宏任务并执行。
微任务通常包括以下操作:
- Promise的回调函数
- Generator函数
- MutationObserver 的回调函数
- process.nextTick(Node.js环境下)
当一个微任务被添加到任务队列中时,它会在当前宏任务执行完成后立即执行,而不是等待下一个宏任务开始执行。这使得微任务可以在当前宏任务执行期间处理异步操作的结果,从而提高应用程序的响应性能。
宏任务与微任务的优先级是怎样的?
在 JavaScript 中,宏任务和微任务的执行优先级是不同的。通常情况下,微任务的优先级高于宏任务,也就是说,在一个宏任务中,如果有微任务存在,那么微任务会优先于宏任务执行。
具体来说,当一个宏任务开始执行时,如果在它的执行过程中产生了微任务,那么这些微任务会被添加到微任务队列中,等待当前宏任务执行完成后立即执行。如果在这个过程中产生了新的微任务,则会一直执行微任务,直到微任务队列为空,然后JavaScript引擎才会继续执行下一个宏任务。
例如,以下代码演示了宏任务和微任务的执行顺序:
console.log('start');
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
console.log('promise');
});
console.log('end');
上述代码中,先执行同步代码 console.log('start') 和 console.log('end')。接着,使用 setTimeout 添加一个宏任务,然后使用 Promise.resolve().then 添加一个微任务。由于微任务优先级高于宏任务,因此 Promise 的回调函数会在 setTimeout 回调函数之前执行。因此,上述代码的输出顺序如下:
start
end
promise
setTimeout