返回

从零开始实现一个符合 Promises/A+ 规范的 Promise

前端

前言

Promise 是 JavaScript 中用于处理异步编程的强大工具。它提供了对异步操作的统一接口,使代码更加清晰和易于维护。然而,要理解 Promise 的工作原理,需要对 Promises/A+ 规范有深入的了解。Promises/A+ 规范定义了 Promise 的行为和实现要求,确保不同实现之间的兼容性。

本文将详细介绍如何从零开始实现一个符合 Promises/A+ 规范的 Promise。通过深入剖析 Promises/A+ 规范,读者可以了解 Promise 的工作原理,掌握 Promise 的实现细节,以便在实际开发中更加熟练地使用 Promise,轻松处理异步编程。

Promise/A+ 规范

Promises/A+ 规范定义了 Promise 的行为和实现要求,确保不同实现之间的兼容性。Promises/A+ 规范的核心思想是将异步操作抽象成一个对象,并提供一套操作该对象的接口。

Promise 的状态有三种:

  • 等待态(Pending):Promise 的初始状态,表示异步操作尚未完成。
  • 已完成态(Fulfilled):异步操作成功完成,Promise 的值被确定。
  • 已拒绝态(Rejected):异步操作失败,Promise 的原因被确定。

Promise 的接口主要有:

  • then() 方法:用于在 Promise 完成后执行回调函数。
  • catch() 方法:用于在 Promise 失败后执行回调函数。
  • finally() 方法:无论 Promise 完成还是失败,都会执行回调函数。

实现 Promise

接下来,我们将从零开始实现一个符合 Promises/A+ 规范的 Promise。

首先,定义 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));
  };

  try {
    executor(resolve, reject);
  } catch (error) {
    reject(error);
  }
}

Promise 构造函数接受一个参数 executor,executor 是一个函数,它接收两个参数 resolve 和 reject。resolve 函数用于在异步操作成功完成后将 Promise 的状态置为已完成态,并将结果值传递给 then() 方法的回调函数。reject 函数用于在异步操作失败后将 Promise 的状态置为已拒绝态,并将失败原因传递给 catch() 方法的回调函数。

然后,定义 then() 方法:

Promise.prototype.then = function (onFulfilled, onRejected) {
  return new Promise((resolve, reject) => {
    this.onFulfilledCallbacks.push((value) => {
      try {
        const result = onFulfilled(value);
        resolve(result);
      } catch (error) {
        reject(error);
      }
    });

    this.onRejectedCallbacks.push((reason) => {
      try {
        const result = onRejected(reason);
        resolve(result);
      } catch (error) {
        reject(error);
      }
    });
  });
};

then() 方法接受两个参数 onFulfilled 和 onRejected,onFulfilled 是一个函数,用于在 Promise 完成后执行,onRejected 是一个函数,用于在 Promise 失败后执行。then() 方法返回一个新的 Promise,该 Promise 的状态取决于 onFulfilled 和 onRejected 函数的执行结果。

最后,定义 catch() 方法:

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

catch() 方法接受一个参数 onRejected,onRejected 是一个函数,用于在 Promise 失败后执行。catch() 方法返回一个新的 Promise,该 Promise 的状态取决于 onRejected 函数的执行结果。

使用 Promise

接下来,我们来看一下如何使用 Promise。

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Hello, world!');
  }, 1000);
});

promise.then((value) => {
  console.log(value); // 'Hello, world!'
});

promise.catch((reason) => {
  console.log(reason); // 'Error!'
});

这段代码首先创建了一个 Promise 实例,并通过 setTimeout() 函数模拟一个异步操作。然后,通过 then() 方法在 Promise 完成后执行一个回调函数,该回调函数将 Promise 的值打印到控制台。最后,通过 catch() 方法在 Promise 失败后执行一个回调函数,该回调函数将 Promise 的失败原因打印到控制台。

结语

本文详细介绍了如何从零开始实现一个符合 Promises/A+ 规范的 Promise。通过深入剖析 Promises/A+ 规范,读者可以了解 Promise 的工作原理,掌握 Promise 的实现细节,以便在实际开发中更加熟练地使用 Promise,轻松处理异步编程。