返回

手写 Promise 剖析其构造过程

前端

前言

在现代 JavaScript 开发中,Promise 已成为异步编程的标准。它提供了一种简单、优雅的方式来处理异步操作,并使代码更加易读和可维护。然而,了解 Promise 的内部机制对于充分利用其优势至关重要。

本文将带你从零开始构建一个 Promise 的 polyfill。通过这个过程,你将深入了解 Promise 的构造过程,并掌握其核心功能。

Promise 的基本概念

Promise 是一种对象,它表示一个异步操作的最终完成或失败。当异步操作完成后,Promise 会进入已完成状态,并存储操作结果。如果操作失败,Promise 也会进入已完成状态,但会存储错误信息。

Promise 有三种状态:

  • 待处理(pending):这是 Promise 的初始状态。在此状态下,异步操作尚未完成。
  • 已完成(fulfilled):异步操作已成功完成,Promise 存储操作结果。
  • 已拒绝(rejected):异步操作已失败,Promise 存储错误信息。

构建 Promise 的 polyfill

现在,让我们开始构建 Promise 的 polyfill。我们将从最基本的概念开始,并逐步构建出 Promise 的核心功能。

1. 构造函数

首先,我们需要定义一个 Promise 构造函数。这个构造函数将接受一个执行器函数作为参数。执行器函数有两个参数:resolve 和 reject。resolve 用于将 Promise 的状态从待处理变为已完成,并存储操作结果。reject 用于将 Promise 的状态从待处理变为已拒绝,并存储错误信息。

function Promise(executor) {
  this.state = 'pending';
  this.value = undefined;
  this.reason = undefined;
  this.onFulfilledCallbacks = [];
  this.onRejectedCallbacks = [];

  const resolve = (value) => {
    if (this.state !== 'pending') {
      return;
    }

    this.state = 'fulfilled';
    this.value = value;

    this.onFulfilledCallbacks.forEach((callback) => {
      callback(value);
    });
  };

  const reject = (reason) => {
    if (this.state !== 'pending') {
      return;
    }

    this.state = 'rejected';
    this.reason = reason;

    this.onRejectedCallbacks.forEach((callback) => {
      callback(reason);
    });
  };

  executor(resolve, reject);
}

2. then 方法

Promise 的 then 方法用于在 Promise 完成后执行指定的回调函数。then 方法接受两个参数:onFulfilled 和 onRejected。onFulfilled 是一个回调函数,它将在 Promise 完成并成功返回结果时执行。onRejected 是一个回调函数,它将在 Promise 完成并返回错误时执行。

Promise.prototype.then = function (onFulfilled, onRejected) {
  if (this.state === 'pending') {
    this.onFulfilledCallbacks.push(onFulfilled);
    this.onRejectedCallbacks.push(onRejected);
  } else if (this.state === 'fulfilled') {
    onFulfilled(this.value);
  } else if (this.state === 'rejected') {
    onRejected(this.reason);
  }

  return this;
};

3. catch 方法

Promise 的 catch 方法用于在 Promise 完成并返回错误时执行指定的回调函数。catch 方法接受一个参数:onRejected。onRejected 是一个回调函数,它将在 Promise 完成并返回错误时执行。

Promise.prototype.catch = function (onRejected) {
  return this.then(undefined, onRejected);
};

4. finally 方法

Promise 的 finally 方法用于在 Promise 完成后始终执行指定的回调函数。finally 方法接受一个参数:onFinally。onFinally 是一个回调函数,它将在 Promise 完成后始终执行,无论 Promise 是成功完成还是失败完成。

Promise.prototype.finally = function (onFinally) {
  return this.then(
    (value) => {
      onFinally();
      return value;
    },
    (reason) => {
      onFinally();
      throw reason;
    }
  );
};

结语

通过构建 Promise 的 polyfill,我们深入了解了 Promise 的构造过程,并掌握了其核心功能。现在,你已经具备了编写高质量 Promise 代码的技能。