Skip to content

手搓一个 Promise

上次中通笔试(A1.5 第二天感谢信,哈哈)看到的问题,还挺有意思的,可以更深入的了解一下Promise

实现步骤

为了手动实现一个简单的Promise,我们需要理解Promise的基本行为和状态管理。一个Promise有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。Promise的状态一旦改变,就不能再变。

Promise 构造函数

js
class MyPromise {
  static PENDING = "pending";
  static FULFILLED = "fulfilled";
  static REJECTED = "rejected";

  constructor(executor) {
    this.state = MyPromise.PENDING;
    this.value = null; // 成功的值
    this.reason = null; // 失败的原因
    this.onFulfilledCallbacks = []; // 成功回调数组
    this.onRejectedCallbacks = []; // 失败回调数组

    const resolve = (value) => {
      if (this.state === MyPromise.PENDING) {
        this.state = MyPromise.FULFILLED;
        this.value = value;
        this.onFulfilledCallbacks.forEach((callback) => callback(this.value));
      }
    };

    const reject = (reason) => {
      if (this.state === MyPromise.PENDING) {
        this.state = MyPromise.REJECTED;
        this.reason = reason;
        this.onRejectedCallbacks.forEach((callback) => callback(this.reason));
      }
    };

    try {
      executor(resolve, reject);
    } catch (error) {
      reject(error);
    }
  }
}
ts
class MyPromise<T> {
  static PENDING = "pending";
  static FULFILLED = "fulfilled";
  static REJECTED = "rejected";

  private state: string;
  private value: T | null;
  private reason: any;
  private onFulfilledCallbacks: Array<(value: T) => void>;
  private onRejectedCallbacks: Array<(reason: any) => void>;

  constructor(executor: (resolve: (value: T) => void, reject: (reason: any) => void) => void) {
    this.state = MyPromise.PENDING;
    this.value = null;
    this.reason = null;
    this.onFulfilledCallbacks = [];
    this.onRejectedCallbacks = [];

    const resolve = (value: T) => {
      if (this.state === MyPromise.PENDING) {
        this.state = MyPromise.FULFILLED;
        this.value = value;
        this.onFulfilledCallbacks.forEach((callback) => callback(this.value as T));
      }
    };

    const reject = (reason: any) => {
      if (this.state === MyPromise.PENDING) {
        this.state = MyPromise.REJECTED;
        this.reason = reason;
        this.onRejectedCallbacks.forEach((callback) => callback(this.reason));
      }
    };

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

实现 then 方法

then方法用于注册成功和失败的回调,并支持链式调用。

js
class MyPromise {
  //...前面的代码
  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      if (this.state === MyPromise.FULFILLED) {
        // 如果提供了成功回调
        if (onFulfilled) {
          try {
            const result = onFulfilled(this.value); // 执行成功回调
            resolve(result); // 将结果传递给新的 Promise
          } catch (error) {
            reject(error); // 如果回调执行出错,新的 Promise 进入拒绝状态
          }
        } else {
          resolve(this.value); // 如果没有提供成功回调,直接将当前值传递给新的 Promise
        }
      } else if (this.state === MyPromise.REJECTED) {
        //// 如果提供了失败回调
        if (onRejected) {
          try {
            const result = onRejected(this.reason);
            resolve(result);
          } catch (error) {
            reject(error);
          }
        } else {
          reject(this.reason);
        }
      } else if (this.state === MyPromise.PENDING) {
        if (onFulfilled) {
          // 将成功回调添加到成功回调数组中
          this.onFulfilledCallbacks.push((value) => {
            try {
              const result = onFulfilled(value); // 执行成功回调
              resolve(result); // 将结果传递给新的 Promise
            } catch (error) {
              reject(error); // 如果回调执行出错,新的 Promise 进入拒绝状态
            }
          });
        } else {
          this.onFulfilledCallbacks.push(resolve); // 如果没有提供成功回调,直接将 resolve 添加到成功回调数组中
        }

        // 如果提供了失败回调
        if (onRejected) {
          // 将失败回调添加到失败回调数组中
          this.onRejectedCallbacks.push((reason) => {
            try {
              const result = onRejected(reason); // 执行失败回调
              resolve(result); // 将结果传递给新的 Promise
            } catch (error) {
              reject(error); // 如果回调执行出错,新的 Promise 进入拒绝状态
            }
          });
        } else {
          this.onRejectedCallbacks.push(reject); // 如果没有提供失败回调,直接将 reject 添加到失败回调数组中
        }
      }
    });
  }
}
ts
class MyPromise<T> {
  // ...前面的代码

  then<TResult = T>(
    onFulfilled?: (value: T) => TResult | MyPromise<TResult>,
    onRejected?: (reason: any) => TResult | MyPromise<TResult>
  ): MyPromise<TResult> {
    return new MyPromise<TResult>((resolve, reject) => {
      if (this.state === MyPromise.FULFILLED) {
        if (onFulfilled) {
          try {
            const result = onFulfilled(this.value as T);
            resolve(result as TResult);
          } catch (error) {
            reject(error);
          }
        } else {
          resolve(this.value as TResult);
        }
      } else if (this.state === MyPromise.REJECTED) {
        if (onRejected) {
          try {
            const result = onRejected(this.reason);
            resolve(result as TResult);
          } catch (error) {
            reject(error);
          }
        } else {
          reject(this.reason);
        }
      } else if (this.state === MyPromise.PENDING) {
        if (onFulfilled) {
          this.onFulfilledCallbacks.push((value: T) => {
            try {
              const result = onFulfilled(value);
              resolve(result as TResult);
            } catch (error) {
              reject(error);
            }
          });
        } else {
          this.onFulfilledCallbacks.push(resolve as (value: T) => void);
        }

        if (onRejected) {
          this.onRejectedCallbacks.push((reason: any) => {
            try {
              const result = onRejected(reason);
              resolve(result as TResult);
            } catch (error) {
              reject(error);
            }
          });
        } else {
          this.onRejectedCallbacks.push(reject);
        }
      }
    });
  }
}

实现 catch 方法

:::code group

js
class MyPromise {
  // ...前面的代码

  catch(onRejected) {
    return this.then(undefined, onRejected);
  }
}
ts
class MyPromise<T> {
  // ...前面的代码

  catch<TResult = never>(onRejected?: (reason: any) => TResult | MyPromise<TResult>): MyPromise<T | TResult> {
    return this.then(undefined, onRejected);
  }
}

:::

如有转载或 CV 的请标注本站原文地址