返回

前端必刷手写题系列 [17]:Promise.all 实现及其问题

前端

前言

大家好,欢迎来到前端必刷手写题系列的第17篇。在上一篇文章中,我们讨论了 Promise 的概念及其使用方式。在本文中,我们将深入探讨一个非常有用的 Promise API:Promise.all。

什么是 Promise.all

Promise.all 是一个静态方法,它接收一个 Promise 对象的数组作为参数,并返回一个新的 Promise 对象。这个新的 Promise 对象代表了所有传入的 Promise 对象都完成时的状态。

如果所有传入的 Promise 对象都成功完成,那么新的 Promise 对象也会成功完成,并返回一个包含所有传入的 Promise 对象结果的数组。

如果任何一个传入的 Promise 对象失败,那么新的 Promise 对象也会失败,并返回一个包含错误信息的对象。

Promise.all 的实现

现在,让我们来实现 Promise.all 函数。首先,我们需要定义一个函数来检查数组中所有的 Promise 对象是否都已完成。

function allSettled(promises) {
  return Promise.all(promises.map((promise) => {
    return promise.then((value) => {
      return { status: "fulfilled", value: value };
    }, (error) => {
      return { status: "rejected", error: error };
    });
  }));
}

allSettled 函数接收一个 Promise 对象的数组作为参数,并返回一个新的 Promise 对象。这个新的 Promise 对象代表了所有传入的 Promise 对象都已完成时的状态。

如果所有传入的 Promise 对象都成功完成,那么新的 Promise 对象也会成功完成,并返回一个包含所有传入的 Promise 对象结果的数组。

如果任何一个传入的 Promise 对象失败,那么新的 Promise 对象也会失败,并返回一个包含错误信息的对象。

接下来,我们需要定义一个函数来处理传入的 Promise 对象数组。

function promiseAll(promises) {
  return new Promise((resolve, reject) => {
    if (promises.length === 0) {
      resolve([]);
      return;
    }

    let results = [];
    let pendingCount = promises.length;

    promises.forEach((promise, index) => {
      promise.then((value) => {
        results[index] = value;
        pendingCount--;

        if (pendingCount === 0) {
          resolve(results);
        }
      }, (error) => {
        reject(error);
      });
    });
  });
}

promiseAll 函数接收一个 Promise 对象的数组作为参数,并返回一个新的 Promise 对象。这个新的 Promise 对象代表了所有传入的 Promise 对象都完成时的状态。

如果所有传入的 Promise 对象都成功完成,那么新的 Promise 对象也会成功完成,并返回一个包含所有传入的 Promise 对象结果的数组。

如果任何一个传入的 Promise 对象失败,那么新的 Promise 对象也会失败,并返回一个包含错误信息的对象。

Promise.all 的问题

Promise.all 函数非常有用,但它也有一些需要注意的问题。

首先,Promise.all 函数并不会保证传入的 Promise 对象的执行顺序。这意味着,即使您传入的 Promise 对象的顺序是 A、B、C,但它们完成的顺序可能是 B、C、A。

其次,Promise.all 函数一旦其中一个 Promise 对象失败,就会立即失败。这意味着,即使其他 Promise 对象还没有完成,Promise.all 函数也不会等待它们完成。

总结

在本文中,我们实现了一个 Promise.all 函数,并讨论了它的潜在问题。Promise.all 函数是一个非常有用的 Promise API,但它也有一些需要注意的问题。在使用 Promise.all 函数时,您需要了解这些问题,并采取相应的措施来避免它们。