返回

约你玩转 Promise 微任务:微观世界里的执行顺序

前端

当我们漫游在 JavaScript 的世界里,时常会惊叹于它那精致的异步机制,而 Promise 和微任务就是其中不可或缺的元素。这些独特的特性携手创造出一个协调有序的异步执行环境,使我们的代码能够更加流畅、可靠地运行。但,当你真正尝试深入解析它们的细微之处时,你可能就会发现一些超乎想象的奥秘。

Promise 的微任务类型

深入研究 Promise,你会发现它内部存在两种截然不同的微任务类型:

  1. Fulfilled Promises(完成的 Promise): 当一个 Promise 顺利完成时,它会创建一个微任务来通知任何等待它结果的代码。
  2. Rejected Promises(拒绝的 Promise): 当一个 Promise 由于某种原因而失败时,它也会创建一个微任务来通知等待它的代码,告知失败的原因。

这些微任务对于 Promise 的正常运行至关重要。它们确保了 Promise 的结果能够及时地传递给等待的代码,从而避免代码陷入阻塞和死锁。

Promise 的执行顺序

Promise 的微任务执行顺序是按照它们创建的顺序严格遵循先进先出(FIFO)的原则,也就是说,先创建的微任务将首先执行。这意味着,如果一个 Promise 首先创建了一个 Fulfilled Promises 微任务,紧接着又创建了一个 Rejected Promises 微任务,那么 Fulfilled Promises 微任务将优先执行。

微任务与宏任务

了解了 Promise 的微任务类型和执行顺序后,我们还需要认识到微任务与宏任务之间的区别。宏任务是那些需要在主线程上执行的任务,而微任务是在宏任务执行期间执行的任务。微任务的执行顺序总是在宏任务之前。

因此,当你看到 Promise 的微任务在宏任务之前执行时,请不要感到惊讶,这是 JavaScript 运行时环境设计使然。这种设计使我们能够在不阻塞主线程的情况下执行异步任务,从而实现更加流畅、响应迅速的应用程序。

深入浅出的示例

为了更好地理解 Promise 微任务的执行顺序,让我们通过一个简单的示例来演示:

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Promise 1 resolved');
  }, 1000);
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('Promise 2 rejected');
  }, 500);
});

promise1.then(result => {
  console.log(result); // "Promise 1 resolved"
}).catch(error => {
  console.log(error);
});

promise2.then(result => {
  console.log(result);
}).catch(error => {
  console.log(error); // "Promise 2 rejected"
});

console.log('Global code execution continues'); // "Global code execution continues"

在代码中:

  1. 首先,我们创建了两个 Promise 实例,promise1 和 promise2。
  2. 然后,我们使用 setTimeout 函数为这两个 Promise 创建了一个微任务。
  3. 接下来的 .then.catch 方法用于监听 Promise 的状态,当 Promise 完成或拒绝时,就会执行相应的回调函数。
  4. 最后,我们在 Promise 之外输出 Global code execution continues 以证明主线程代码继续执行。

运行这段代码,你会看到:

  1. 首先输出 Global code execution continues,表明主线程代码继续执行。
  2. 然后,你会看到 Promise 2 rejected,表明 promise2 被拒绝了。
  3. 最后,你会看到 Promise 1 resolved,表明 promise1 被成功地解析了。

这个示例清楚地演示了 Promise 微任务的执行顺序。即使 promise2 先创建,但由于 promise1 的微任务先执行,所以它的结果先被记录到控制台。

结语

Promise 微任务是 JavaScript 世界中的一个重要概念,掌握它对于理解 Promise 的工作原理和异步代码的执行顺序至关重要。通过本指南,你已经了解了 Promise 微任务的类型、执行顺序以及与宏任务的区别。希望这些知识能够帮助你更深入地理解 JavaScript 的异步执行机制,并编写出更加健壮、可维护的代码。