实现 Promise.allSettled

手写 Promise.allSettled 方法

问题

实现 Promise.allSettled,等待所有 Promise 完成(无论成功或失败),返回每个 Promise 的结果状态。

解答

Promise.myAllSettled = function (promises) {
  // 将输入转为数组
  const promiseArray = Array.from(promises);

  // 空数组直接返回
  if (promiseArray.length === 0) {
    return Promise.resolve([]);
  }

  return new Promise((resolve) => {
    const results = [];
    let settledCount = 0;

    promiseArray.forEach((promise, index) => {
      // 用 Promise.resolve 包装,处理非 Promise 值
      Promise.resolve(promise)
        .then((value) => {
          results[index] = { status: 'fulfilled', value };
        })
        .catch((reason) => {
          results[index] = { status: 'rejected', reason };
        })
        .finally(() => {
          settledCount++;
          // 所有 Promise 都已 settled
          if (settledCount === promiseArray.length) {
            resolve(results);
          }
        });
    });
  });
};

测试

const p1 = Promise.resolve(1);
const p2 = Promise.reject('error');
const p3 = new Promise((resolve) => setTimeout(() => resolve(3), 100));

Promise.myAllSettled([p1, p2, p3]).then((results) => {
  console.log(results);
  // [
  //   { status: 'fulfilled', value: 1 },
  //   { status: 'rejected', reason: 'error' },
  //   { status: 'fulfilled', value: 3 }
  // ]
});

关键点

  • allSettled 永远返回 fulfilled 状态,不会 reject
  • 结果对象格式:成功是 { status: 'fulfilled', value },失败是 { status: 'rejected', reason }
  • Promise.resolve() 包装输入,兼容非 Promise 值
  • 结果数组顺序与输入顺序一致,用 index 保证位置
  • Promise.all 的区别:all 遇到 reject 立即终止,allSettled 等待全部完成