手写Promise

81 阅读12分钟

Promise/A+标准

Promises/A+是一种用于标准化JavaScript中Promise对象行为的规范。

Promise对象状态:Pending(待定)、Fulfilled(已解决)和Rejected(已拒绝)。状态只能从PendingFulfilled或从PendingRejected,且一旦改变无法再次修改。

Promise对象可以使用resolve()函数将状态从Pending转换到Fulfilled,也可以使用reject()函数将状态从Pending转换到Rejected

每个Promise必须有一个then方法,该方法接受两个参数:onFulfilledonRejected,分别对应Promise成功和失败的情况。这些回调函数在Promise状态改变时被调用。

Promises/A+

Promises/A+中文网

构造函数—constructor

constructor接收一个executor回调函数作为异步任务。在构造函数中初始化状态、值、回调函数栈,并定义resolvereject函数传递给回调函数。当在异步任务中执行完成可以调用resolve/rejec,获取最终值。

  • #status:当前Promise的状态
  • #value:Promise完成结果
  • #reason:Promise拒绝原因
  • #callBackStack:回调栈,用于存储每次调用then函数时传入的回调
  • resolve():修改Promise的状态至Fulfilled ,传递给executor
  • reject():修改Promise的状态至Rejected,传递给executor
  • #runAllCallbacks():执行回调栈中存储的回调方法(见下文实现)
class MyPromise {
  #status;
  #value;
  #reason;
  #callBackStack;

  static PENDING = "pending";
  static FULFILLED = "fulfilled";
  static REJECTED = "rejected";

  constructor(executor) {
    this.#status = MyPromise.PENDING;
    this.#value = undefined;
    this.#reason = undefined;
    this.#callBackStack = [];

    // resolve和reject不能写在原型上,this指向会受影响,指向window
    const resolve = (value) => {
      // 只有等待状态能够修改状态-2.1.1
      // 当状态是完成时,不再处理-2.1.2
      if (this.#status === MyPromise.PENDING) {
        this.#status = MyPromise.FULFILLED;
        this.#value = value;
        // 状态变更后执行所有回调
        this.#runAllCallbacks();
      }
    };

    const reject = (reason) => {
      // 只有等待状态能够修改状态-2.1.1
      // 当状态是拒绝时,不再处理-2.1.3
      if (this.#status === MyPromise.PENDING) {
        this.#status = MyPromise.REJECTED;
        this.#reason = reason;
        // 状态变更后执行所有回调
        this.#runAllCallbacks();
      }
    };

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

then函数

then()函数接收onFulfilledonRejected函数,分别用于完成和拒绝的回调。then()函数返回一个新的Promise,并存储回调信息,在异步任务完成/拒绝时依次调用存储的回调函数。

  • onFulfilled():执行完成结果的回调,如果非函数则默认返回相同值
  • onRejected():执行拒绝结果的回调,如果非函数则默认抛出相同错误
  • #callBackStack:每次调用then就向栈里存储当前的回调信息,由于then可以多次调用,所以回调函数有多个,是个数组
  • #runAllCallbacks():执行存储在栈中的所有回调函数,根据状态执行onFulfilledonRejected
  • #runSingleCallback():把单个回调放入微任务等待执行。如果回调函数结果是promise,需要根据返回的promise获取最终值
  /**
   * then方法,接收两个参数,onFulfilled和onRejected。
   * 分别对应Promise的成功回调和失败回调。
   * 如果这两个参数不是函数,则会被替换为默认的处理方式。
   * 之后将回调信息添加到回调栈中,所有回调会在状态完成/拒绝后运行。
   *
   * @param {Function} onFulfilled - 成功回调
   * @param {Function} onRejected - 失败回调
   * @returns {MyPromise} 返回一个新的MyPromise对象
   */
  then(onFulfilled, onRejected) {
    // 处理onFulfilled/onRejected是非函数的情况
    // onFulfilled 返回相同的值-2.2.7.3
    // onRejected 返回相同的拒绝原因-2.2.7.4
    onFulfilled =
      typeof onFulfilled === "function" ? onFulfilled : (value) => value;
    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : (reason) => {
            throw reason;
          };

    return new MyPromise((resolve, reject) => {
      // 记录then函数传递的回调信息
      // 可能多次调用then,所以是一个数组-2.2.6
      this.#callBackStack.push({ onFulfilled, onRejected, resolve, reject });
      this.#runAllCallbacks();
    });
  }
  
     /**
   * 执行回调栈中存储的回调方法
   * 首先判断状态,状态是完成/拒绝时才继续执行,并执行对应回调
   */
  #runAllCallbacks() {
    if (this.#status === MyPromise.PENDING) return;
    while (this.#callBackStack.length) {
      const { onFulfilled, onRejected, resolve, reject } =
        this.#callBackStack.shift();

      if (this.#status === MyPromise.FULFILLED) {
        this.#runSingleCallback(onFulfilled, this.#value, resolve, reject);
      } else {
        this.#runSingleCallback(onRejected, this.#reason, resolve, reject);
      }
    }
  }

  /**
   * 判断对象是否是Promise Like对象
   * @param {Object/Function} obj - 需要被检测的对象
   * @return {Boolean}
   */
  #isPromiseLike(obj) {
    if (obj !== null && (typeof obj === "object" || typeof obj === "function"))
      return typeof obj.then === "function";
    return false;
  }

  /**
   * 在微队列中运行函数,根据运行环境的不同,选择不同的方式去执行传入的函数fn。
   *
   * @param {Function} fn - 需要被异步执行的函数
   * 如果当前环境是Node.js,使用process.nextTick方法来异步执行;
   * 如果当前环境是浏览器,使用MutationObserver来异步执行;
   * 如果都不是上述环境,则使用setTimeout来异步执行。
   */
  #runMicroTask(fn) {
    if (typeof process === "object" && typeof process.nextTick === "function") {
      // node环境
      process.nextTick(fn);
    } else if (typeof MutationObserver === "function") {
      // 浏览器环境
      const ob = new MutationObserver(fn);
      const textNode = document.createTextNode("1");
      ob.observe(textNode, {
        characterData: true,
      });
      textNode.data = 2;
    } else {
      setTimeout(fn, 0);
    }
  }

  /**
   * 执行单个回调函数,首先运行一个微任务,然后尝试执行回调函数并处理其结果。
   * 如果回调函数返回的结果是一个Promise对象,那么它将根据这个Promise的状态来决定是resolve还是reject。
   * 如果回调函数执行过程中抛出异常,那么它将拒绝完成。
   * @param {Function} callback - 回调函数
   * @param {Any} value - 参数
   * @param {Function} resolve - Promise对象的resolve方法
   * @param {Function} reject - Promise对象的reject方法
   */
  #runSingleCallback(callback, value, resolve, reject) {
    this.#runMicroTask(() => {
      try {
        const result = callback(value);
        if (this.#isPromiseLike(result)) {
          // 回调函数返回结果是promise3 => 根据promise3状态执行resolve或rejected-2.3.2
          result.then(resolve, reject);
        } else {
          // 回调是函数 => 执行回调,返回回调结果-2.3.3.3
          resolve(result);
        }
      } catch (error) {
        // 执行回调时存在异常 => 拒绝完成-2.2.7.2
        reject(error);
      }
    });
  }

其他方法

Promise/A+中没有规定的方法,可见MDN

Promise - JavaScript | MDN

catch函数

  /**
   * 处理Promise对象的拒绝状态的函数。当Promise对象被拒绝时,会调用这个函数。then函数的简写
   * @param {Function} onRejected - 回调函数,用于处理Promise对象的拒绝状态
   * @return {Promise} 返回一个新的MyPromise对象
   */
  catch(onRejected) {
    return this.then(undefined, onRejected);
  }

finally函数

  /**
   * 无论是resolve还是reject,都会执行onFinally回调函数
   * @param {Function} onFinally - 回调函数,在Promise结束时被调用
   * @return {Promise} 返回一个新的MyPromise对象
   */
  finally(onFinally) {
    return this.then(
      (data) => {
        // onFinally 不接收任何参数,
        // finally是透明的,即状态一致、返回相同的值-MDN finally描述第2、3点
        onFinally();
        return data;
      },
      (error) => {
        onFinally();
        throw error;
      }
    );
  }

resolve函数

  /**
   * 静态方法,创建一个返回给定的值的已完成MyPromise对象。
   * 如果传入的是一个MyPromise,则返回这个MyPromise;
   * 如果输入值是类似Promise的对象(即拥有then方法),则使用其then方法来解析新的Promise;
   * 如果不是,直接用输入值来完成新的Promise。
   * @param {any} value - 值
   * @return {MyPromise} 返回一个新的MyPromise对象
   */
  static resolve(value) {
    if (value instanceof MyPromise) return value;
    let _resolve, _reject;
    const p = new MyPromise((resolve, reject) => {
      _resolve = resolve;
      _reject = reject;
    });

    if (p.#isPromiseLike(value)) {
      value.then(_resolve, _reject);
    } else {
      _resolve(value);
    }

    return p;
  }

reject函数

   /**
   * 静态方法,创建一个返回给定原因的已拒绝的Promise对象。
   *
   * @param {any} reason - 拒绝原因
   * @return {MyPromise} 返回一个新的MyPromise对象
   */
  static reject(reason) {
    return new MyPromise((_, reject) => {
      reject(reason);
    });
  }

race函数

   /**
   * 静态方法,获取给定promise列表中最早完成或拒绝的promise
   * @param {Array} promises - Promise对象数组
   * @return {MyPromise} 返回一个新的PMyPromise对象
   */
  static race(promises) {
    return new MyPromise((resolve, reject) => {
      if (!Array.isArray(promises)) {
        reject(new TypeError(`${promises} is not array`));
      }

      // 遍历所有promise
      promises.forEach((promise) => {
        // 可能包含非 promise 值,使用MyPromise.resolve
        MyPromise.resolve(promise)
          .then((data) => {
            resolve(data);
          })
          .catch((error) => {
            reject(error);
          });
      });
    });
  }

all函数

   /**
   * 静态方法,处理多个Promise。
   * 如果所有Promise成功,返回一个包含所有结果的数组;
   * 如果有一个Promise拒绝,返回第一个拒绝的Promise,并将第一个遇到的失败原因作为拒绝的原因。
   * @param {Array} promises - Promise对象数组
   * @returns {Promise} 返回一个新的Promise
   */
  static all(promises) {
    return new MyPromise((resolve, reject) => {
      if (!Array.isArray(promises)) {
        reject(new TypeError(`${promises} is not array`));
      }

      let resolvedCount = 0; // promise完成个数
      const result = new Array(promises.length); // 每个promise执行结果
      promises.forEach((promise, index) => {
        MyPromise.resolve(promise)
          .then((data) => {
            // 如果当前的promise执行成功,将结果存储到result中
            resolvedCount++;
            result[index] = data;

            if (resolvedCount >= promises.length) {
              resolve(result);
            }
          })
          .catch((error) => {
            reject(error);
          });
      });
    });
  }

any函数

   /**
   * 静态方法,接收一个Promise数组,并返回新的Promise。
   * 当数组中任何Promise完成时,新的Promise就会立即完成,并返回第一个完成的Promise的结果。
   * 如果所有的Promise都拒绝,那么新的Promise也会拒绝,并返回所有拒绝的原因。
   * @param {Array} promises - Promise数组
   * @returns {MyPromise} 返回一个新的Promise
   * @throws {TypeError} 如果传入的参数不是一个数组,会抛出TypeError异常
   * @throws {AggregateError} 如果所有的Promise都失败,会抛出一个AggregateError异常,该异常包含了所有失败的原因
   */
  static any(promises) {
    return new MyPromise((resolve, reject) => {
      if (!Array.isArray(promises)) {
        reject(new TypeError(`${promises} is not array`));
      }
      if (!promises.length) {
        // 空数组直接拒绝
        reject(new AggregateError([], "All promises were rejected"));
        return;
      }

      let rejectedCount = 0; // promise拒绝个数
      const result = new Array(promises.length);

      promises.forEach((promise, index) => {
        MyPromise.resolve(promise).then(
          (data) => {
            // 如果有完成的promise直接完成
            resolve(data);
          },
          (error) => {
            rejectedCount++;
            result[index] = error;

            if (rejectedCount >= promises.length) {
              reject(new AggregateError(result, "All promises were rejected"));
            }
          }
        );
      });
    });
  }

allSettled函数

 /**
   * 静态方法,接收一个Promise数组,并返回新的Promise。
   * 当数组的Promise都结束时,会返回一个数组,数组中含有所有Promise的结果
   * @param {Array} promises - Promise数组
   * @return {MyPromise} 返回一个新的Promise
   */
  static allSettled(promises) {
    return new MyPromise((resolve, reject) => {
      if (!Array.isArray(promises)) {
        reject(new TypeError(`${promises} is not array`));
      }
      if (!promises.length) {
        // 空数组直接完成
        resolve([]);
        return;
      }

      let count = 0;
      const result = new Array(promises.length);

      promises.forEach((promise, index) => {
        MyPromise.resolve(promise)
          .then(
            (value) => {
              result[index] = { status: MyPromise.FULFILLED, value };
            },
            (reason) => {
              result[index] = { status: MyPromise.REJECTED, reason };
            }
          )
          .finally(() => {
            count++;
            if (count >= promises.length) resolve(result);
          });
      });
    });
  }

测试

then链式调用:

const p = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve("success1");
  }, 1000);
});
p.then((data) => {
  console.log("then1", data);
  return "success2";
}).then((data) => {
  console.log("then2", data);
});

// 结果:
// then1 success1
// then2 success2

then返回原生promise:

const p = new MyPromise((resolve) => {
  setTimeout(() => {
    resolve(1);
  }, 1000);
});
p.then((data) => {
  console.log("then1", data);
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(2), 1000;
    });
  });
}).then((data) => {
  console.log("then1", data);
});

// 结果:
// then1 1
// then2 2

async/await使用:

const delay = (ms = 1000) => {
  return new MyPromise((resolve) => {
    setTimeout(() => {
      resolve("延时结束");
    }, ms);
  });
};
const test = async () => {
  const result = await delay();
  console.log("result", result);
  console.log(1);
};
test();

// 结果:
// result 延时结束
// 1

微队列:

setTimeout(() => {
  console.log(1);
}, 0);
new MyPromise((resolve) => {
  console.log(2);
  resolve(3);
}).then((data) => {
  console.log(3);
});

// 结果:2 3 1

race、all、any、allSettled函数:

const p1 = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    // resolve("p1");
    reject("p1");
  }, 1000);
});
const p2 = new MyPromise((resolve) => {
  setTimeout(() => {
    resolve("p2");
  }, 2000);
});

MyPromise.race([p1, p2]).then(
  (data) => {
    console.log("data", data);
  },
  (error) => {
    console.log("error", error);
  }
);
MyPromise.all([p1, p2]).then(
  (data) => {
    console.log("data", data);
  },
  (error) => {
    console.log("error", error);
  }
);
MyPromise.any([p1, p2]).then(
  (data) => {
    console.log("data", data);
  },
  (error) => {
    console.log("error", error);
  }
);
MyPromise.allSettled([p1, p2]).then(
  (data) => {
    console.log("data", data);
  },
  (error) => {
    console.log("error", error);
  }
);

// 结果:
// error p1
// error p1
// data p2
// data [({ status: "rejected", reason: "p1" }, { status: "fulfilled", value: "p2" })];

MyPromise

class MyPromise {
  #status;
  #value;
  #reason;
  #callBackStack;

  static PENDING = "pending";
  static FULFILLED = "fulfilled";
  static REJECTED = "rejected";

  constructor(executor) {
    this.#status = MyPromise.PENDING;
    this.#value = undefined;
    this.#reason = undefined;
    this.#callBackStack = [];

    // resolve和reject不能写在原型上,this指向会受影响,指向window
    const resolve = (value) => {
      // 只有等待状态能够修改状态-2.1.1
      // 当状态是完成时,不再处理-2.1.2
      if (this.#status === MyPromise.PENDING) {
        this.#status = MyPromise.FULFILLED;
        this.#value = value;
        // 状态变更后执行所有回调
        this.#runAllCallbacks();
      }
    };

    const reject = (reason) => {
      // 只有等待状态能够修改状态-2.1.1
      // 当状态是拒绝时,不再处理-2.1.3
      if (this.#status === MyPromise.PENDING) {
        this.#status = MyPromise.REJECTED;
        this.#reason = reason;
        // 状态变更后执行所有回调
        this.#runAllCallbacks();
      }
    };

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

  /**
   * 执行回调栈中存储的回调方法
   * 首先判断状态,状态是完成/拒绝时才继续执行,并执行对应回调
   */
  #runAllCallbacks() {
    if (this.#status === MyPromise.PENDING) return;
    while (this.#callBackStack.length) {
      const { onFulfilled, onRejected, resolve, reject } =
        this.#callBackStack.shift();

      if (this.#status === MyPromise.FULFILLED) {
        this.#runSingleCallback(onFulfilled, this.#value, resolve, reject);
      } else {
        this.#runSingleCallback(onRejected, this.#reason, resolve, reject);
      }
    }
  }

  /**
   * 判断对象是否是Promise Like对象
   * @param {Object/Function} obj - 需要被检测的对象
   * @return {Boolean}
   */
  #isPromiseLike(obj) {
    if (obj !== null && (typeof obj === "object" || typeof obj === "function"))
      return typeof obj.then === "function";
    return false;
  }

  /**
   * 在微队列中运行函数,根据运行环境的不同,选择不同的方式去执行传入的函数fn。
   *
   * @param {Function} fn - 需要被异步执行的函数
   * 如果当前环境是Node.js,使用process.nextTick方法来异步执行;
   * 如果当前环境是浏览器,使用MutationObserver来异步执行;
   * 如果都不是上述环境,则使用setTimeout来异步执行。
   */
  #runMicroTask(fn) {
    if (typeof process === "object" && typeof process.nextTick === "function") {
      // node环境
      process.nextTick(fn);
    } else if (typeof MutationObserver === "function") {
      // 浏览器环境
      const ob = new MutationObserver(fn);
      const textNode = document.createTextNode("1");
      ob.observe(textNode, {
        characterData: true,
      });
      textNode.data = 2;
    } else {
      setTimeout(fn, 0);
    }
  }

  /**
   * 执行单个回调函数,首先运行一个微任务,然后尝试执行回调函数并处理其结果。
   * 如果回调函数返回的结果是一个Promise对象,那么它将根据这个Promise的状态来决定是resolve还是reject。
   * 如果回调函数执行过程中抛出异常,那么它将拒绝完成。
   * @param {Function} callback - 回调函数
   * @param {Any} value - 参数
   * @param {Function} resolve - Promise对象的resolve方法
   * @param {Function} reject - Promise对象的reject方法
   */
  #runSingleCallback(callback, value, resolve, reject) {
    this.#runMicroTask(() => {
      try {
        const result = callback(value);
        if (this.#isPromiseLike(result)) {
          // 回调函数返回结果是promise3 => 根据promise3状态执行resolve或rejected-2.3.2
          result.then(resolve, reject);
        } else {
          // 回调是函数 => 执行回调,返回回调结果-2.3.3.3
          resolve(result);
        }
      } catch (error) {
        // 执行回调时存在异常 => 拒绝完成-2.2.7.2
        reject(error);
      }
    });
  }

  /**
   * then方法,接收两个参数,onFulfilled和onRejected。
   * 分别对应Promise的成功回调和失败回调。
   * 如果这两个参数不是函数,则会被替换为默认的处理方式。
   * 之后将回调信息添加到回调栈中,所有回调会在状态完成/拒绝后运行。
   *
   * @param {Function} onFulfilled - 成功回调
   * @param {Function} onRejected - 失败回调
   * @returns {MyPromise} 返回一个新的MyPromise对象
   */
  then(onFulfilled, onRejected) {
    // 处理onFulfilled/onRejected是非函数的情况
    // onFulfilled 返回相同的值-2.2.7.3
    // onRejected 返回相同的拒绝原因-2.2.7.4
    onFulfilled =
      typeof onFulfilled === "function" ? onFulfilled : (value) => value;
    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : (reason) => {
            throw reason;
          };

    return new MyPromise((resolve, reject) => {
      // 记录then函数传递的回调信息
      // 可能多次调用then,所以是一个数组-2.2.6
      this.#callBackStack.push({ onFulfilled, onRejected, resolve, reject });
      this.#runAllCallbacks();
    });
  }

  /**
   * 处理Promise对象的拒绝状态的函数。当Promise对象被拒绝时,会调用这个函数。then函数的简写
   * @param {Function} onRejected - 回调函数,用于处理Promise对象的拒绝状态
   * @return {Promise} 返回一个新的MyPromise对象
   */
  catch(onRejected) {
    return this.then(undefined, onRejected);
  }

  /**
   * 无论是resolve还是reject,都会执行onFinally回调函数
   * @param {Function} onFinally - 回调函数,在Promise结束时被调用
   * @return {Promise} 返回一个新的MyPromise对象
   */
  finally(onFinally) {
    return this.then(
      (data) => {
        // onFinally 不接收任何参数,
        // finally是透明的,即状态一致、返回相同的值-MDN finally描述第2、3点
        onFinally();
        return data;
      },
      (error) => {
        onFinally();
        throw error;
      }
    );
  }

  /**
   * 静态方法,创建一个返回给定的值的已完成MyPromise对象。
   * 如果传入的是一个MyPromise,则返回这个MyPromise;
   * 如果输入值是类似Promise的对象(即拥有then方法),则使用其then方法来解析新的Promise;
   * 如果不是,直接用输入值来完成新的Promise。
   * @param {any} value - 值
   * @return {MyPromise} 返回一个新的MyPromise对象
   */
  static resolve(value) {
    if (value instanceof MyPromise) return value;
    let _resolve, _reject;
    const p = new MyPromise((resolve, reject) => {
      _resolve = resolve;
      _reject = reject;
    });

    if (p.#isPromiseLike(value)) {
      value.then(_resolve, _reject);
    } else {
      _resolve(value);
    }

    return p;
  }

  /**
   * 静态方法,创建一个返回给定原因的已拒绝的Promise对象。
   *
   * @param {any} reason - 拒绝原因
   * @return {MyPromise} 返回一个新的MyPromise对象
   */
  static reject(reason) {
    return new MyPromise((_, reject) => {
      reject(reason);
    });
  }

  /**
   * 静态方法,获取给定promise列表中最早完成或拒绝的promise
   * @param {Array} promises - Promise对象数组
   * @return {MyPromise} 返回一个新的PMyPromise对象
   */
  static race(promises) {
    return new MyPromise((resolve, reject) => {
      if (!Array.isArray(promises)) {
        reject(new TypeError(`${promises} is not array`));
      }

      // 遍历所有promise
      promises.forEach((promise) => {
        // 可能包含非 promise 值,使用MyPromise.resolve
        MyPromise.resolve(promise)
          .then((data) => {
            resolve(data);
          })
          .catch((error) => {
            reject(error);
          });
      });
    });
  }

  /**
   * 静态方法,处理多个Promise。
   * 如果所有Promise成功,返回一个包含所有结果的数组;
   * 如果有一个Promise拒绝,返回第一个拒绝的Promise,并将第一个遇到的失败原因作为拒绝的原因。
   * @param {Array} promises - Promise对象数组
   * @returns {Promise} 返回一个新的Promise
   */
  static all(promises) {
    return new MyPromise((resolve, reject) => {
      if (!Array.isArray(promises)) {
        reject(new TypeError(`${promises} is not array`));
      }

      let resolvedCount = 0; // promise完成个数
      const result = new Array(promises.length); // 每个promise执行结果
      promises.forEach((promise, index) => {
        MyPromise.resolve(promise)
          .then((data) => {
            // 如果当前的promise执行成功,将结果存储到result中
            resolvedCount++;
            result[index] = data;

            if (resolvedCount >= promises.length) {
              resolve(result);
            }
          })
          .catch((error) => {
            reject(error);
          });
      });
    });
  }

  /**
   * 静态方法,接收一个Promise数组,并返回新的Promise。
   * 当数组中任何Promise完成时,新的Promise就会立即完成,并返回第一个完成的Promise的结果。
   * 如果所有的Promise都拒绝,那么新的Promise也会拒绝,并返回所有拒绝的原因。
   * @param {Array} promises - Promise数组
   * @returns {MyPromise} 返回一个新的Promise
   * @throws {TypeError} 如果传入的参数不是一个数组,会抛出TypeError异常
   * @throws {AggregateError} 如果所有的Promise都失败,会抛出一个AggregateError异常,该异常包含了所有失败的原因
   */
  static any(promises) {
    return new MyPromise((resolve, reject) => {
      if (!Array.isArray(promises)) {
        reject(new TypeError(`${promises} is not array`));
      }
      if (!promises.length) {
        // 空数组直接拒绝
        reject(new AggregateError([], "All promises were rejected"));
        return;
      }

      let rejectedCount = 0; // promise拒绝个数
      const result = new Array(promises.length);

      promises.forEach((promise, index) => {
        MyPromise.resolve(promise).then(
          (data) => {
            // 如果有完成的promise直接完成
            resolve(data);
          },
          (error) => {
            rejectedCount++;
            result[index] = error;

            if (rejectedCount >= promises.length) {
              reject(new AggregateError(result, "All promises were rejected"));
            }
          }
        );
      });
    });
  }

  /**
   * 静态方法,接收一个Promise数组,并返回新的Promise。
   * 当数组的Promise都结束时,会返回一个数组,数组中含有所有Promise的结果
   * @param {Array} promises - Promise数组
   * @return {MyPromise} 返回一个新的Promise
   */
  static allSettled(promises) {
    return new MyPromise((resolve, reject) => {
      if (!Array.isArray(promises)) {
        reject(new TypeError(`${promises} is not array`));
      }
      if (!promises.length) {
        // 空数组直接完成
        resolve([]);
        return;
      }

      let count = 0;
      const result = new Array(promises.length);

      promises.forEach((promise, index) => {
        MyPromise.resolve(promise)
          .then(
            (value) => {
              result[index] = { status: MyPromise.FULFILLED, value };
            },
            (reason) => {
              result[index] = { status: MyPromise.REJECTED, reason };
            }
          )
          .finally(() => {
            count++;
            if (count >= promises.length) resolve(result);
          });
      });
    });
  }
}