遵循 Promise/A+ 标准,手写实现一个 Promise 函数,附注释

Promise/A+规范

Promise/A+测试工具

遵循 Promise/A+ 标准,手写实现一个 Promise 函数,包含以下功能函数:

  • Promise.reject
  • Promise.all
  • Promise.race
  • Promise.prototype.catch
  • Promise.prototype.finally
  • Promise.allSettled

Typescript 实现 ,附注释:

const PENDING = "pending" as const;
const FULFILLED = "fulfilled" as const;
const REJECTED = "rejected" as const;

type PromiseStatus = typeof PENDING | typeof FULFILLED | typeof REJECTED;

/**
 * 自定义Promise实现(遵循Promise/A+规范)
 * @template T Promise解析值的类型
 */
export class PromiseTest<T = unknown> {
  // 当前Promise状态(初始为pending)
  private status: PromiseStatus = PENDING;
  // 成功状态时的值(仅当status为fulfilled时有值),默认为 undefined
  private value: T | undefined = undefined;
  // 失败状态时的原因(仅当status为rejected时有值),默认为 undefined
  private reason: unknown = undefined;
  // 存储成功回调的数组(用于pending状态时暂存回调)
  private onResolvedCallbacks: Array<() => void> = [];
  // 存储失败回调的数组(用于pending状态时暂存回调)
  private onRejectedCallbacks: Array<() => void> = [];

  /**
   * 构造函数,接收执行器函数
   * @param executor 执行器函数,接收resolve和reject作为参数
   * @throws 执行器同步抛出异常时会直接调用reject
   */
  constructor(
    executor: (
      resolve: (value: T) => void,
      reject: (reason: unknown) => void
    ) => void
  ) {
    // resolve函数(Promise/A+ 2.1.2 成功状态转换)
    const resolve = (value: T) => {
      // 仅当状态为pending时允许转换
      if (this.status === PENDING) {
        this.status = FULFILLED;
        this.value = value;
        // 触发所有暂存的成功回调(Promise/A+ 2.2.6.1 顺序执行)
        this.onResolvedCallbacks.forEach((fn) => fn());
      }
    };
    // reject函数(Promise/A+ 2.1.3 失败状态转换)
    const reject = (reason: unknown) => {
      if (this.status === PENDING) {
        this.status = REJECTED;
        this.reason = reason;
        // 触发所有暂存的失败回调(Promise/A+ 2.2.6.2 顺序执行)
        this.onRejectedCallbacks.forEach((fn) => fn());
      }
    };

    // 执行器可能同步抛出异常(Promise/A+ 2.1.3.2 异常处理)
    try {
      executor(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }

  /**
   * 解析then回调的返回值x,决定新Promise的状态(Promise/A+ 2.3)
   * @template U 新Promise解析值的类型
   * @param promise2 新Promise实例(需要避免循环引用)
   * @param x then回调的返回值(可能是普通值、Promise或thenable)
   * @param resolve 新Promise的resolve函数
   * @param reject 新Promise的reject函数
   */
  private static resolvePromise<U>(
    promise2: PromiseTest<U>,
    x: unknown,
    resolve: (value: U) => void,
    reject: (reason: unknown) => void
  ) {
    // 循环引用检测(Promise/A+ 2.3.1)
    if (promise2 === x) {
      return reject(new TypeError("Chaining cycle detected for promise"));
    }

    // 防止重复调用resolve/reject
    let called = false;

    try {
      // 处理thenable对象(Promise/A+ 2.3.3)
      if ((typeof x === "object" && x !== null) || typeof x === "function") {
        const then = (x as any).then;
        // 如果x是具有then方法的对象/函数(thenable)
        if (typeof then === "function") {
          // 调用x.then(不要写成 x.then,直接 then.call 就可以了 因为 x.then 会再次取值,Object.defineProperty),传递新的resolve/reject(Promise/A+ 2.3.3.3)
          then.call(
            x,
            (y: unknown) => {
              if (called) return; // 已调用过,直接返回
              called = true;
              // 递归解析y(可能是另一个Promise)
              PromiseTest.resolvePromise(promise2, y, resolve, reject);
            },
            (r: unknown) => {
              if (called) return;
              called = true;
              // 失败时直接拒绝新Promise
              reject(r);
            }
          );
        } else {
          // x是对象/函数但无then方法:直接成功(Promise/A+ 2.3.3.4)
          resolve(x as U);
        }
      } else {
        // 处理普通值,如果 x 是个普通值就直接返回 resolve 作为结果(Promise/A+ 2.3.4)
        resolve(x as U);
      }
    } catch (err) {
      // 异常处理(Promise/A+ 2.3.3.2)
      if (called) return;
      called = true;
      reject(err);
    }
  }

  /**
   * 注册成功/失败回调,返回新的Promise实例
   * @template U 成功回调返回值类型
   * @template V 失败回调返回值类型
   * @param onFulfilled 成功回调(可选,默认透传值)
   * @param onRejected 失败回调(可选,默认抛异常)
   * @returns 新的Promise实例,状态由回调执行结果决定
   */
  then<U = T, V = never>(
    onFulfilled?: (value: T) => U | PromiseLike<U>,
    onRejected?: (reason: unknown) => V | PromiseLike<V>
  ): PromiseTest<U | V> {
    // 处理未传回调的情况(Promise/A+ 2.2.1 可选回调)
    const _onFulfilled =
      typeof onFulfilled === "function"
        ? onFulfilled
        : (value: T) => value as unknown as U; // 默认透传值

    const _onRejected =
      typeof onRejected === "function"
        ? onRejected
        : (reason: unknown) => {
            throw reason;
          }; // 默认抛异常

    // 创建新Promise实例(Promise/A+ 2.2.7 链式调用)
    const promise2 = new PromiseTest<U | V>((resolve, reject) => {
      // 成功处理函数
      const handleFulfilled = () => {
        // 异步执行回调(Promise/A+ 2.2.4 异步要求)
        setTimeout(() => {
          try {
            // 执行成功回调并获取返回值x(Promise/A+ 2.2.7.1)
            const x = _onFulfilled(this.value!);
            // 解析x并决定promise2的状态(关键逻辑)
            PromiseTest.resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            // 回调抛出异常时,promise2拒绝(Promise/A+ 2.2.7.2)
            reject(e);
          }
        }, 0);
      };

      // 失败处理函数
      const handleRejected = () => {
        setTimeout(() => {
          try {
            const x = _onRejected(this.reason!);
            PromiseTest.resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      };

      // 根据当前状态分支处理
      if (this.status === FULFILLED) {
        // 已成功:直接执行成功处理
        handleFulfilled();
      } else if (this.status === REJECTED) {
        // 已失败:直接执行失败处理
        handleRejected();
      } else {
        // 未决状态(pending):暂存回调,待状态变更时触发
        this.onResolvedCallbacks.push(handleFulfilled);
        this.onRejectedCallbacks.push(handleRejected);
      }
    });

    return promise2;
  }

  /**
   * 返回一个已解决的Promise实例(ES6规范)
   * @param value 要解决的值(可能是普通值、Promise或thenable)
   * @returns 新的Promise实例
   */
  static resolve<U>(value: U | PromiseLike<U>): PromiseTest<U> {
    // 如果value本身是PromiseTest实例,直接返回
    if (value instanceof PromiseTest) {
      return value;
    }
    // 否则创建新Promise并解析value
    return new PromiseTest<U>((resolve) => {
      // 调用resolvePromise处理thenable
      PromiseTest.resolvePromise(
        new PromiseTest<U>((resolveInner) => {
          // 避免立即执行
          resolve = resolveInner; // 替换为外部resolve
        }),
        value,
        resolve,
        (err) => {
          throw err;
        }
      );
    });
  }

  /**
   * 返回一个已拒绝的Promise实例(ES6规范)
   * @param reason 拒绝的原因
   * @returns 新的Promise实例
   */
  static reject<U>(reason: unknown): PromiseTest<U> {
    return new PromiseTest<U>((_, reject) => {
      reject(reason);
    });
  }

  /**
   * 等待所有Promise完成,返回结果数组(ES6规范)
   * @param promises 可迭代的Promise数组
   * @returns 新的Promise实例,解决时为结果数组,拒绝时为第一个拒绝的原因
   */
  static all<U>(promises: Iterable<PromiseLike<U>>): PromiseTest<U[]> {
    return new PromiseTest<U[]>((resolve, reject) => {
      const results: U[] = [];
      let count = 0;
      const iterable = Array.from(promises);
      const len = iterable.length;

      // 处理空数组情况(直接解决)
      if (len === 0) {
        resolve([]);
        return;
      }

      iterable.forEach((promise, index) => {
        PromiseTest.resolve(promise).then(
          (value) => {
            results[index] = value;
            count++;
            if (count === len) {
              resolve(results);
            }
          },
          (err) => reject(err) // 任意一个拒绝则整体拒绝
        );
      });
    });
  }

  /**
   * 返回第一个完成(解决或拒绝)的Promise的结果(ES6规范)
   * @param promises 可迭代的Promise数组
   * @returns 新的Promise实例,解决/拒绝取决于第一个完成的Promise
   */
  static race<U>(promises: Iterable<PromiseLike<U>>): PromiseTest<U> {
    return new PromiseTest<U>((resolve, reject) => {
      Array.from(promises).forEach((promise) => {
        PromiseTest.resolve(promise).then(resolve, reject);
      });
    });
  }

  /**
   * 等待所有Promise完成,返回包含每个结果状态的数组(ES2020规范)
   * @param promises 可迭代的Promise数组
   * @returns 新的Promise实例,解决时为{ status: 'fulfilled', value }或{ status: 'rejected', reason }的数组
   */
  static allSettled<U>(
    promises: Iterable<PromiseLike<U>>
  ): PromiseTest<
    Array<
      | { status: "fulfilled"; value: U }
      | { status: "rejected"; reason: unknown }
    >
  > {
    return new PromiseTest((resolve) => {
      const results: Array<
        | { status: "fulfilled"; value: U }
        | { status: "rejected"; reason: unknown }
      > = [];
      let count = 0;
      const iterable = Array.from(promises);
      const len = iterable.length;

      if (len === 0) {
        resolve([]);
        return;
      }

      iterable.forEach((promise, index) => {
        PromiseTest.resolve(promise).then(
          (value) => {
            results[index] = { status: "fulfilled", value };
            count++;
            if (count === len) resolve(results);
          },
          (reason) => {
            results[index] = { status: "rejected", reason };
            count++;
            if (count === len) resolve(results);
          }
        );
      });
    });
  }

  /**
   * 注册拒绝回调(ES6规范,等价于then(undefined, onRejected))
   * @param onRejected 拒绝时的回调函数
   * @returns 新的Promise实例
   */
  catch<V = never>(
    onRejected?: (reason: unknown) => V | PromiseLike<V>
  ): PromiseTest<T | V> {
    return this.then(undefined, onRejected);
  }

  /**
   * 注册最终回调(ES2018规范,无论解决/拒绝都会执行)
   * @param onFinally 最终执行的回调函数(无参数)
   * @returns 新的Promise实例,状态与原Promise一致
   */
  finally(onFinally: () => void): PromiseTest<T> {
    return this.then(
      (value) => {
        onFinally();
        return value;
      },
      (reason) => {
        onFinally();
        throw reason;
      }
    );
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值