返回

剖析 Promise 的优先执行原理:揭秘 JavaScript 引擎的幕后逻辑

前端

引言

在 JavaScript 的异步编程世界中,了解 Promise 和 setTimeout 的执行顺序至关重要。违反直觉的是,Promise 中的代码往往先于 setTimeout 执行。本文将深入探讨 JavaScript 引擎的内部机制,揭示这一现象背后的原理。

Promise:异步编程的利器

Promise 是一种异步编程模型,它允许我们在非阻塞方式下处理异步操作。当异步操作完成时,Promise 将被解析或拒绝,触发相应的回调函数执行。

setTimeout:计时器函数

setTimeout 是一种全局函数,它允许我们在指定的时间延迟后执行代码。它接受两个参数:要执行的函数和延迟时间。

JavaScript 引擎的事件循环

为了理解 Promise 和 setTimeout 的执行顺序,我们必须了解 JavaScript 引擎的事件循环。事件循环是一个不断运行的循环,它检查是否还有事件需要处理,并执行相应的代码。事件可以是点击事件、网络请求或 setTimeout 回调等。

Promise 的执行优先级

Promise 的优先级高于 setTimeout,因为 Promise 的回调被认为是 "微任务",而 setTimeout 的回调是 "宏任务"。

微任务在宏任务之前被处理。因此,当 JavaScript 引擎遇到一个 Promise,它会将其回调添加到微任务队列中。当事件循环处理微任务队列时,Promise 回调将立即执行。

setTimeout 的延迟执行

另一方面,setTimeout 的回调被添加到宏任务队列中。宏任务队列在微任务队列之后被处理。这意味着 setTimeout 回调将在处理完所有微任务后才执行。

实际示例

以下代码演示了 Promise 和 setTimeout 的执行顺序:

console.log("开始");

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log("Promise 已解析");
    resolve();
  }, 100);
});

setTimeout(() => {
  console.log("setTimeout 已执行");
}, 0);

await promise;

console.log("结束");

输出结果为:

开始
Promise 已解析
setTimeout 已执行
结束

如你所见,Promise 中的代码在 setTimeout 之前执行。

结论

Promise 中的代码优先于 setTimeout 执行,因为 Promise 的回调是微任务,而 setTimeout 的回调是宏任务。JavaScript 引擎的事件循环首先处理微任务队列,然后才处理宏任务队列。了解这一优先级对于编写有效且响应迅速的异步 JavaScript 代码至关重要。