返回

揭秘 Promise.all 源码,探寻并行执行的秘密

前端

Promise.all:异步编程中的利器

并行执行,轻松搞定异步任务

在当今快节奏的数字世界中,异步编程已经成为一项必备技能,它允许我们同时处理多个任务,从而提高效率并创建更具响应性的应用程序。Promise.all 是JavaScript中一个强大的工具,它使我们能够轻松并行执行多个异步任务,并处理它们的成败情况。

Promise.all的内部运作机制

Promise.all 函数接受一个包含Promise 对象的可迭代对象(例如数组)作为参数,并返回一个新的Promise 对象。这个新Promise 的状态取决于传入Promise 的状态:

  • 如果所有传入的Promise 都成功解决,则新Promise 将以包含所有解决值(按传入Promise 的顺序排列)的数组作为参数成功解决。
  • 如果传入Promise 中的任何一个被拒绝,则新Promise 将被拒绝,拒绝原因是第一个被拒绝的Promise 的拒绝原因。

以下是Promise.all 的源代码:

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

    let result = [];
    let pendingPromises = promises.length;

    for (let i = 0; i < promises.length; i++) {
      Promise.resolve(promises[i]).then(
        (value) => {
          result[i] = value;
          pendingPromises--;
          if (pendingPromises === 0) {
            resolve(result);
          }
        },
        (error) => {
          reject(error);
        }
      );
    }
  });
};

执行流程

当调用Promise.all 时,它会创建一个新的Promise 对象并立即返回。然后,它遍历传入的Promise 对象,并为每个Promise 创建了一个内部Promise 对象。内部Promise 对象会等待传入的Promise 解决或拒绝,并在解决或拒绝时更新结果数组或触发拒绝。

当所有传入的Promise 都解决时,Promise.all 将用结果数组成功解决。如果其中任何一个Promise 被拒绝,Promise.all 将立即被拒绝。

功能特性

Promise.all 具有以下几个关键特性:

  • 并行执行: 传入的Promise 会并行执行,而不是按顺序执行。
  • 按顺序收集结果: 即使Promise 不是按顺序解决,结果也会按传入Promise 的顺序收集在数组中。
  • 一旦拒绝就停止: 如果传入的Promise 中的任何一个被拒绝,Promise.all 将立即被拒绝,而不会等待其他Promise 解决。

示例代码

以下示例展示了如何使用Promise.all 来并行获取多个用户的详细信息:

const userPromises = [
  fetchUser(1),
  fetchUser(2),
  fetchUser(3),
];

Promise.all(userPromises).then((users) => {
  // users 是包含所有用户详细信息的数组
});

结论

Promise.all 是异步编程中的一个宝贵工具,它允许我们轻松并行执行多个异步任务。通过理解其内部运作机制,我们获得了对它的功能特性和执行过程的更深入了解。掌握Promise.all 的使用和限制,将极大地提升我们的异步编程技能。

常见问题解答

  1. Promise.all什么时候使用?
    当我们需要并行执行多个异步任务并获取它们的结果或处理拒绝时,可以使用Promise.all

  2. Promise.all的结果如何收集?
    结果按传入Promise 的顺序收集在一个数组中。

  3. 如果Promise.all中的一个Promise被拒绝,会发生什么?
    Promise.all 将立即被拒绝,拒绝原因是第一个被拒绝的Promise 的拒绝原因。

  4. Promise.all如何处理空输入?
    如果输入为空数组或nullPromise.all 将立即返回一个包含空数组的新Promise

  5. 可以使用 Promise.all处理XMLHttpRequest对象吗?
    是的,可以使用Promise.all 将XMLHttpRequest对象转换成Promise ,并对多个XMLHttpRequest对象进行并行处理。