手写 Promise.all

142 阅读2分钟

手写 Promise.all 是一个很好的练习,可以帮助理解 Promise 的内部实现和并发处理的逻辑。Promise.all 的作用是等待所有的 Promise 实例都完成(resolve 或 reject)后返回一个结果。如果所有的 Promise 都成功(resolve),则返回一个包含所有结果的数组;如果有任何一个 Promise 失败(reject),则立即返回失败的结果。

实现思路

  1. 初始化状态:创建一个新的 Promise 实例。
  2. 收集结果:遍历传入的 promises 数组,收集每个 Promise 的结果。
  3. 处理完成状态:当所有 Promise 都 resolve 时,返回一个包含所有结果的数组。
  4. 处理失败状态:如果有任何一个 Promise reject,则立即返回失败的结果。

代码实现

下面是一个完整的 Promise.all 的手写实现:

function myPromiseAll(promises) {
  return new Promise((resolve, reject) => {
    const results = []; // 存储每个 Promise 的结果
    let completedCount = 0; // 记录已完成的 Promise 数量

    // 遍历 promises 数组
    promises.forEach((promise, index) => {
      promise.then(
        (result) => {
          results[index] = result; // 存储结果
          completedCount++; // 增加已完成的数量

          // 如果所有 Promise 都已完成
          if (completedCount === promises.length) {
            resolve(results);
          }
        },
        (error) => {
          reject(error); // 有任何一个 Promise 失败,立即拒绝
        }
      );
    });
  });
}

// 测试代码
const promise1 = Promise.resolve(1);
const promise2 = Promise.resolve(2);
const promise3 = Promise.resolve(3);

myPromiseAll([promise1, promise2, promise3])
  .then((results) => {
    console.log('All resolved:', results); // 输出: All resolved: [1, 2, 3]
  })
  .catch((error) => {
    console.error('Error:', error);
  });

const promise4 = Promise.reject(new Error('Failed'));
myPromiseAll([promise1, promise2, promise4])
  .then((results) => {
    console.log('All resolved:', results);
  })
  .catch((error) => {
    console.error('Error:', error); // 输出: Error: Failed
  });

解释

  1. 创建新的 Promise 实例myPromiseAll 函数返回一个新的 Promise 实例。
  2. 收集结果:使用 results 数组来存储每个 Promise 的结果。
  3. 计数器completedCount 变量用于记录已完成的 Promise 数量。
  4. 处理完成状态:当所有 Promise 都 resolve 时,通过 resolve 回调函数返回 results 数组。
  5. 处理失败状态:如果有任何一个 Promise reject,则通过 reject 回调函数立即返回错误。

测试代码

上面的测试代码展示了如何使用 myPromiseAll 函数。当所有 Promise 都成功时,输出结果数组;如果有任何一个 Promise 失败,则输出错误信息。

总结

通过手写 Promise.all,我们可以更好地理解 Promise 的内部实现和并发处理的逻辑。这种方法不仅有助于学习 Promise 的基本概念,还能加深对并发编程的理解。在实际开发中,这种实现方式也能帮助我们更好地处理多个异步任务的并发执行。