返回

揭秘 JavaScript 的执行顺序:任务、微任务、队列与代码运行流程

前端

JavaScript 的执行顺序是一个复杂且令人着迷的话题,它直接影响着我们编写的代码的运行方式和行为。为了深入理解 JavaScript 的执行机制,我们需要了解任务、微任务、队列和代码执行顺序等关键概念。

任务和微任务

JavaScript 执行的最小单元被称为任务。当执行 JavaScript 代码时,会创建一个任务队列,其中包含所有要执行的任务。主线程会从队列中轮流取出任务并执行它们。每个任务都是一个独立的执行单元,它可能会执行同步或异步操作。

微任务是比任务更小的执行单元。它们是由 Promise、MutationObserver 和事件循环的其他部分创建的。微任务队列是单独于任务队列的,在主线程执行任务之间执行微任务。

队列和代码执行顺序

JavaScript 代码执行主要发生在以下队列中:

  • 任务队列:包含所有要执行的任务,按先进先出 (FIFO) 原则执行。
  • 微任务队列:包含所有要执行的微任务,也在 FIFO 原则下执行。
  • 宏任务队列:一个特殊的队列,仅包含 setTimeout、setInterval 和 requestAnimationFrame 等宏任务。

代码执行顺序遵循以下规则:

  1. 主线程从任务队列中取出一个任务并执行它。
  2. 在执行任务的过程中,如果遇到了任何微任务,它们会被添加到微任务队列中。
  3. 当任务执行完毕,主线程会从微任务队列中取出一个微任务并执行它。
  4. 此过程重复,直到所有任务和微任务都已执行。
  5. 如果主线程空闲,它会从宏任务队列中取出一个宏任务并执行它。

实际案例

为了更好地理解代码执行顺序,考虑以下示例:

console.log('script start');

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

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

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

console.log('script end');

在这种情况下,预期的执行顺序是:

  1. script start
  2. script end
  3. promise1
  4. promise2
  5. setTimeout

这与实际执行顺序一致,因为主线程将按照任务和微任务的执行顺序执行代码。