Promise.all 实现

手写 Promise.all 方法

问题

从零实现 Promise.all 方法。

解答

function promiseAll(promises) {
  return new Promise((resolve, reject) => {
    // 处理非数组输入
    const arr = Array.from(promises);
    const results = [];
    let completed = 0;

    // 空数组直接返回
    if (arr.length === 0) {
      resolve(results);
      return;
    }

    arr.forEach((promise, index) => {
      // 用 Promise.resolve 包装,处理非 Promise 值
      Promise.resolve(promise)
        .then((value) => {
          // 按原顺序存储结果
          results[index] = value;
          completed++;

          // 全部完成后 resolve
          if (completed === arr.length) {
            resolve(results);
          }
        })
        .catch((error) => {
          // 任意一个失败就 reject
          reject(error);
        });
    });
  });
}

测试

// 测试1:全部成功
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const p3 = new Promise((resolve) => setTimeout(() => resolve(3), 100));

promiseAll([p1, p2, p3]).then(console.log); // [1, 2, 3]

// 测试2:包含非 Promise 值
promiseAll([1, 2, Promise.resolve(3)]).then(console.log); // [1, 2, 3]

// 测试3:有一个失败
const p4 = Promise.reject('error');
promiseAll([p1, p4, p3]).catch(console.log); // 'error'

// 测试4:空数组
promiseAll([]).then(console.log); // []

关键点

  • 返回一个新的 Promise
  • Promise.resolve() 包装每个元素,兼容非 Promise 值
  • 结果数组要保持原顺序,用索引赋值而非 push
  • 用计数器判断是否全部完成
  • 任意一个 reject 就立即 reject 整体