返回

微任务、宏任务与 Event-Loop的紧密关系及区别

前端

JavaScript 是一个单线程的脚本语言,这意味着它一次只能执行一个任务。当一个任务正在执行时,其他任务必须等待。然而,JavaScript 也支持异步编程,这意味着它允许在不阻塞主线程的情况下执行某些任务。异步任务由浏览器在一个单独的线程中执行,当任务完成后,浏览器会将结果发送回主线程。

微任务和宏任务是 JavaScript 中异步任务的两种类型。微任务是在主线程上执行的异步任务,而宏任务是在单独的线程上执行的异步任务。微任务的优先级高于宏任务,这意味着当主线程空闲时,它会优先执行微任务。

Event-Loop 是一个循环,它不断地检查是否有新的任务需要执行。当 Event-Loop 检测到一个新的任务时,它会将其添加到适当的队列中。如果任务是一个微任务,它将被添加到微任务队列中。如果任务是一个宏任务,它将被添加到宏任务队列中。

当主线程空闲时,Event-Loop 会从微任务队列中取出一个任务并执行它。当微任务队列为空时,Event-Loop 会从宏任务队列中取出一个任务并执行它。

微任务和宏任务之间存在一些关键区别。

  • 微任务是在主线程上执行的,而宏任务是在单独的线程上执行的。
  • 微任务的优先级高于宏任务,这意味着当主线程空闲时,它会优先执行微任务。
  • 微任务的执行顺序与它们被创建的顺序相同,而宏任务的执行顺序则不一定与它们被创建的顺序相同。

理解微任务、宏任务和 Event-Loop 的概念对于理解 JavaScript 的异步编程至关重要。这些概念可以帮助您编写更健壮、更有效率的代码。

实际案例

为了更好地理解微任务、宏任务和 Event-Loop,我们来看一个实际的例子。

console.log('script start');

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

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

console.log('script end');

当这段代码执行时,以下事件将发生:

  1. 主线程开始执行脚本。
  2. 主线程输出 "script start" 到控制台。
  3. 主线程创建一个 setTimeout 任务并将其添加到宏任务队列中。
  4. 主线程创建一个 Promise 任务并将其添加到微任务队列中。
  5. 主线程输出 "script end" 到控制台。
  6. 主线程空闲,它从微任务队列中取出 Promise 任务并执行它。
  7. Promise 任务输出 "Promise" 到控制台。
  8. 主线程空闲,它从宏任务队列中取出 setTimeout 任务并执行它。
  9. setTimeout 任务输出 "setTimeout" 到控制台。

在这个例子中,我们可以看到微任务的优先级高于宏任务。即使 setTimeout 任务被创建在 Promise 任务之前,但它是在 Promise 任务之后执行的。这是因为 Promise 任务是一个微任务,而 setTimeout 任务是一个宏任务。

结论

微任务、宏任务和 Event-Loop 是 JavaScript 中异步编程的重要组成部分。理解这些概念对于编写更健壮、更有效率的代码至关重要。