返回

微任务和宏任务,谁先谁后?

前端

在JavaScript中,微任务和宏任务的概念对于理解代码执行的顺序和异步编程至关重要。这两个概念通常会一同出现,但是它们的工作方式却截然不同。

微任务

微任务是 JavaScript 引擎在执行宏任务期间遇到的任务。微任务的优先级高于宏任务,这意味着它们会在宏任务完成之前执行。常见的微任务包括:

  • Promise 的 .then() 和 .catch() 方法
  • MutationObserver的回调函数
  • setImmediate() 函数
  • requestAnimationFrame()函数

微任务存储在微任务队列中,该队列是JavaScript引擎维护的一个特殊队列。当引擎遇到微任务时,它会将其添加到微任务队列中。当微任务队列中没有宏任务时,引擎会从微任务队列中取出微任务并执行它们。

宏任务

宏任务是 JavaScript 引擎在执行脚本期间遇到的任务。宏任务的优先级低于微任务,这意味着它们会在微任务执行完毕之后才执行。常见的宏任务包括:

  • 脚本代码
    *setTimeout()函数
    *setInterval()函数
    *XMLHttpRequest 对象

宏任务存储在宏任务队列中,该队列是 JavaScript 引擎维护的另一个特殊队列。当引擎遇到宏任务时,它会将其添加到宏任务队列中。当宏任务队列中没有微任务时,引擎会从宏任务队列中取出宏任务并执行它们。

执行顺序

微任务和宏任务的执行顺序如下:

  1. 首先,引擎执行脚本代码。
  2. 当引擎遇到微任务时,它会将其添加到微任务队列中。
  3. 当引擎遇到宏任务时,它会将其添加到宏任务队列中。
  4. 当微任务队列中没有微任务时,引擎会从微任务队列中取出微任务并执行它们。
  5. 当宏任务队列中没有宏任务时,引擎会从宏任务队列中取出宏任务并执行它们。

代码示例

以下代码演示了微任务和宏任务的执行顺序:

console.log('Start');

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

// 宏任务
setTimeout(() => {
  console.log('宏任务 1');
}, 0);

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

// 宏任务
setTimeout(() => {
  console.log('宏任务 2');
}, 0);

console.log('End');

运行这段代码会输出以下结果:

Start
微任务 1
微任务 2
End
宏任务 1
宏任务 2

从输出结果可以看出,微任务在宏任务之前执行。即使宏任务的延迟时间为 0,微任务也会先于宏任务执行。

总结

微任务和宏任务是 JavaScript 中两个重要的概念,它们决定了代码执行的顺序。微任务的优先级高于宏任务,这意味着它们会在宏任务之前执行。常见的微任务包括 Promise 的 .then() 和 .catch() 方法、MutationObserver 的回调函数、setImmediate() 函数和 requestAnimationFrame() 函数。常见的宏任务包括脚本代码、setTimeout() 函数、setInterval() 函数和 XMLHttpRequest 对象。