返回

Event Loop 探秘:微任务、宏任务与单线程世界的奥秘

前端

序言:揭开 JavaScript 单线程的神秘面纱

JavaScript 是当今世界最流行的编程语言之一,它被广泛应用于 Web 开发、移动开发、游戏开发等领域。JavaScript 的一大特色是单线程执行,这意味着它一次只能执行一个任务。

单线程执行模型虽然简单易懂,但却带来了一个问题:当 JavaScript 执行一个耗时较长的任务时,整个浏览器都会被阻塞,导致其他任务无法执行。为了解决这个问题,JavaScript 引入了微任务和宏任务的概念,从而实现异步编程。

微任务与宏任务:异步编程的基石

微任务

微任务是指在当前执行栈中执行的任务,也是 JavaScript 中优先级最高的任务。当 JavaScript 引擎执行完一个任务后,它会检查微任务队列,如果有微任务,则立即执行它们。微任务队列是一个先进先出的队列,这意味着最早加入的微任务将首先执行。

宏任务

宏任务是指在当前执行栈之外执行的任务,包括诸如 setTimeout、setInterval、I/O 操作等。宏任务队列也是一个先进先出的队列,但它与微任务队列不同,宏任务队列中的任务只有在微任务队列为空时才会执行。

Event Loop:协调微任务与宏任务的执行

Event Loop 是 JavaScript 中的一个核心概念,它负责协调微任务和宏任务的执行。Event Loop 会不断地从微任务队列和宏任务队列中取出任务并执行它们。如果微任务队列中有任务,则 Event Loop 会优先执行微任务。如果微任务队列为空,则 Event Loop 会执行宏任务队列中的任务。

微任务与宏任务的执行顺序

在 Event Loop 的协调下,微任务和宏任务的执行顺序遵循以下规则:

  1. 当 JavaScript 引擎执行一个任务时,它会将该任务的微任务添加到微任务队列中。
  2. 当 JavaScript 引擎执行完一个任务后,它会检查微任务队列,如果有微任务,则立即执行它们。
  3. 当微任务队列为空时,JavaScript 引擎会检查宏任务队列,如果有宏任务,则执行它们。
  4. Event Loop 会不断地重复上述步骤,直到所有任务都执行完成。

实例演示:揭秘 Event Loop 的运作过程

为了更好地理解 Event Loop 的运作过程,我们来看一个实例演示:

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

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

console.log('同步任务');

当我们运行这段代码时,会看到以下输出:

同步任务
微任务
宏任务

这个实例演示了微任务和宏任务的执行顺序。首先,JavaScript 引擎执行同步任务,即 console.log('同步任务')。然后,JavaScript 引擎将宏任务 setTimeout 添加到宏任务队列中,并将微任务 Promise.resolve().then() 添加到微任务队列中。

当 JavaScript 引擎执行完同步任务后,它会检查微任务队列,发现微任务队列中有任务,于是立即执行微任务 Promise.resolve().then()。微任务执行完成后,JavaScript 引擎会检查宏任务队列,发现宏任务队列中有任务,于是执行宏任务 setTimeout

小试牛刀:一题检验你的理解

现在,我们来做一道题检验一下你的理解:

在一个 JavaScript 程序中,有以下代码:

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

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

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

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

console.log('同步任务');

请问,这段代码的输出是什么?

答案:

同步任务
微任务 1
微任务 2
宏任务 1
宏任务 2

结语

通过本文,你已经对 JavaScript 中的 Event Loop、微任务、宏任务有了深入的了解。掌握了这些知识,你将能够更好地理解 JavaScript 的异步编程机制,并编写出更加健壮、高效的 JavaScript 程序。