返回

事件循环、DOM 渲染、宏任务和微任务之间的关系

前端

在 JavaScript 世界中,事件循环、DOM 渲染、宏任务和微任务是四个基本概念。它们共同协作,为我们提供了交互且响应迅速的 Web 应用程序。了解这些概念之间的关系对于理解 JavaScript 应用程序的执行至关重要。

事件循环

事件循环是一个无穷无尽的循环,它不断地从任务队列中检索任务并执行它们。任务队列是一个 FIFO(先进先出)队列,其中包含要执行的函数。

当 JavaScript 引擎遇到事件时,它会将事件处理程序函数添加到任务队列中。当事件循环检索到事件处理程序时,它会执行该函数。

DOM 渲染

DOM(文档对象模型)是 HTML 文档的树形表示。当 JavaScript 代码改变 DOM 时,浏览器将重新渲染受影响的部分以反映这些更改。

宏任务

宏任务是需要花费大量时间才能完成的任务。例如,以下代码创建了一个宏任务,该任务将 setTimeout 回调函数添加到任务队列中:

setTimeout(() => {
  // 这个函数将在 1000 毫秒后执行
}, 1000);

微任务

微任务是需要在当前调用栈执行完后立即执行的任务。例如,以下代码创建了一个微任务,该任务将 Promise 回调函数添加到任务队列中:

Promise.resolve().then(() => {
  // 这个函数将在当前调用栈执行完后立即执行
});

它们之间的关系

事件循环、DOM 渲染、宏任务和微任务之间的关系可以如下图所示:

事件循环、DOM 渲染、宏任务和微任务之间的关系

在事件循环的每一步中,它都会执行以下操作:

  1. 执行当前调用栈中的所有任务。
  2. 执行所有微任务。
  3. 渲染 DOM。
  4. 执行所有宏任务。

当执行完任务队列中的所有任务时,事件循环将重新开始。

优先级

微任务的优先级高于宏任务。这意味着微任务将在宏任务之前执行。

这是因为微任务对于 JavaScript 应用程序的响应性至关重要。例如,当您在文本字段中键入文本时,浏览器会创建一个微任务来更新 DOM。如果不优先处理微任务,文本字段将无法立即更新,从而导致延迟和不响应的用户界面。

示例

为了更好地理解事件循环、DOM 渲染、宏任务和微任务之间的关系,让我们考虑以下示例:

// 这是一个宏任务
setTimeout(() => {
  console.log("宏任务");
}, 0);

// 这是一个微任务
Promise.resolve().then(() => {
  console.log("微任务");
});

// 这是一个微任务
setTimeout(() => {
  console.log("微任务");
}, 0);

// 这是一个宏任务
setTimeout(() => {
  console.log("宏任务");
}, 0);

当执行此代码时,将打印以下内容:

微任务
微任务
宏任务
宏任务

这是因为微任务优先于宏任务。因此,尽管宏任务先于微任务添加到任务队列中,但它们却在微任务之后执行。

结论

事件循环、DOM 渲染、宏任务和微任务是理解 JavaScript 应用程序执行的关键概念。了解这些概念之间的关系对于编写响应迅速、交互良好的应用程序至关重要。