返回

手把手教你写出符合Promises/A+规范的Promise

前端

揭秘Promises/A+规范

Promises/A+规范是JavaScript异步编程的标准规范,它定义了Promise对象的行为和实现方式。该规范旨在确保不同环境和平台上的Promise对象具有统一的行为,从而方便开发人员编写可靠、可维护的异步代码。

Promises/A+规范主要包括以下几个要求:

  • Promise对象必须具有then方法,用于注册成功和失败回调函数。
  • then方法必须返回一个新的Promise对象,该对象代表异步操作的结果。
  • then方法可以被多次调用,每次调用都会注册一个新的回调函数。
  • Promise对象必须具有一个状态,该状态可以是pending、fulfilled或rejected。
  • pending状态表示异步操作尚未完成。
  • fulfilled状态表示异步操作已成功完成。
  • rejected状态表示异步操作已失败。
  • Promise对象只能从pending状态转换到fulfilled状态或rejected状态,且只能转换一次。
  • Promise对象的then方法只能在pending状态下被调用。
  • Promise对象的then方法在pending状态下被调用时,会立即执行成功或失败回调函数,并将结果返回给新的Promise对象。
  • Promise对象的then方法在fulfilled状态下被调用时,会立即执行成功回调函数,并将结果返回给新的Promise对象。
  • Promise对象的then方法在rejected状态下被调用时,会立即执行失败回调函数,并将原因返回给新的Promise对象。
  • Promise对象的then方法可以被多次调用,每次调用都会注册一个新的回调函数。
  • Promise对象的then方法可以返回一个值或另一个Promise对象。如果返回一个值,则新的Promise对象将以fulfilled状态解析。如果返回另一个Promise对象,则新的Promise对象将以该Promise对象的状态解析。

实战:手写符合Promises/A+规范的Promise

接下来,我们将一步步手写一个符合Promises/A+规范的Promise。为了便于理解,我们使用ES6语法来编写代码。

// 1. 定义Promise类
class Promise {
  constructor(executor) {
    // 1.1 初始化状态为pending
    this.state = 'pending';
    // 1.2 成功回调函数队列
    this.onFulfilledCallbacks = [];
    // 1.3 失败回调函数队列
    this.onRejectedCallbacks = [];
    // 1.4 执行executor函数
    executor(this.resolve.bind(this), this.reject.bind(this));
  }

  // 2.1 解析Promise
  resolve(value) {
    // 2.1.1 如果状态不是pending,则忽略
    if (this.state !== 'pending') {
      return;
    }
    // 2.1.2 将状态改为fulfilled
    this.state = 'fulfilled';
    // 2.1.3 依次执行成功回调函数
    this.onFulfilledCallbacks.forEach((callback) => {
      callback(value);
    });
  }

  // 2.2 拒绝Promise
  reject(reason) {
    // 2.2.1 如果状态不是pending,则忽略
    if (this.state !== 'pending') {
      return;
    }
    // 2.2.2 将状态改为rejected
    this.state = 'rejected';
    // 2.2.3 依次执行失败回调函数
    this.onRejectedCallbacks.forEach((callback) => {
      callback(reason);
    });
  }

  // 3.1 then方法
  then(onFulfilled, onRejected) {
    // 3.1.1 返回一个新的Promise对象
    return new Promise((resolve, reject) => {
      // 3.1.2 将成功回调函数添加到队列中
      this.onFulfilledCallbacks.push(() => {
        // 3.1.2.1 调用成功回调函数
        const result = onFulfilled(value);
        // 3.1.2.2 解析新的Promise对象
        resolve(result);
      });

      // 3.1.3 将失败回调函数添加到队列中
      this.onRejectedCallbacks.push(() => {
        // 3.1.3.1 调用失败回调函数
        const reason = onRejected(reason);
        // 3.1.3.2 拒绝新的Promise对象
        reject(reason);
      });
    });
  }
}

常见用法

Promise的用法非常简单,只需要实例化一个Promise对象,并传入一个executor函数。executor函数有两个参数,分别是resolve和reject。resolve函数用于解析Promise对象,将结果传递给then方法的成功回调函数。reject函数用于拒绝Promise对象,将原因传递给then方法的失败回调函数。

// 创建一个Promise对象
const promise = new Promise((resolve, reject) => {
  // 模拟异步操作
  setTimeout(() => {
    // 成功解析Promise对象
    resolve('Hello, world!');
  }, 2000);
});

// 使用then方法注册成功回调函数
promise.then((result) => {
  console.log(result); // 输出: Hello, world!
});

注意事项

在使用Promise时,需要注意以下几点:

  • Promise对象只能被解析或拒绝一次。
  • then方法只能在pending状态下被调用。
  • then方法可以被多次调用,每次调用都会注册一个新的回调函数。
  • then方法可以返回一个值或另一个Promise对象。如果返回一个值,则新的Promise对象将以fulfilled状态解析。如果返回另一个Promise对象,则新的Promise对象将以该Promise对象的状态解析。

结语

Promise是JavaScript异步编程的利器,它可以帮助我们编写更清晰、更易维护的代码。本文从零开始,一步步讲解了如何手写一个符合Promises/A+规范的Promise,并介绍了Promise的常见用法和注意事项。希望这篇文章能够对你有帮助,并帮助你更好地掌握Promise这一强大的工具。