Promise.all和Promise.allSettled之间的区别是什么?

134 阅读3分钟

Promise.all 和 是在JavaScript中处理承诺数组的两种不同方式。让我们来比较一下它们,并谈谈什么时候使用这两种方法比较合适。Promise.allSettled

它们如何相似

Promise.allPromise.allSettled 的主要相似之处是,这两个方法都以一个承诺数组作为参数。你使用它们是因为你有一组你想在继续前进之前处理的承诺。不过这也是相似之处的结束。正如我们将看到的,这些方法实际处理承诺的方式是非常不同的。

最大的区别 处理拒绝

处理拒绝是Promise.allPromise.allSettled 之间的最大区别。如果你想让你的诺言组在其中一个诺言被拒绝时立即失败,你应该使用Promise.all 。然而,如果你想在继续前进之前给所有的Promise一个机会,可以考虑Promise.allSettled

让我们来看看下面这个函数的例子,该函数返回一个Promise,该Promise有50/50的机会解决或拒绝,并将在一个随机的时间后解决。

function randomPromise(id) {
  return new Promise(function (res, rej) {
    setTimeout(function () {
      if (Math.random() > 0.5) {
        res(id);
      } else {
        rej(`${id} failed randomly!`);
      }
    }, Math.random() * 1000);
  });
}

Promise.all

在处理拒绝时,Promise.all 是全有或全无。如果一个Promise拒绝了,Promise.all 立即停止并调用catch 方法并报告错误。

Promise.all([randomPromise(1), randomPromise(2), randomPromise(3)])
  .then(function (data) {
    console.log(data);
  })
  .catch(function (err) {
    console.error(err);
  });

如果三个Promise都成功解决,你会看到[1, 2, 3] ,记录在控制台。然而,更有可能的是,其中一个承诺失败。一旦失败,你会看到该承诺的错误被打印到控制台。

2 failed randomly!

注意一些事情。

  • 尽管第一个和第三个Promise可能已经成功解决,但我们从未进入then 方法,我们只是直接进入catch
  • 你永远不会在控制台中看到两个错误,因为当其中一个Promise拒绝时,Promise.all 立即失败。

Promise.allSettled

Promise.allSettled 会继续前进,让所有的Promise解析或拒绝(即结算),然后再给你结果。 不会拒绝,它在 方法中给你所有你需要的信息。Promise.allSettled then

让我们看一下前面的例子,你就会明白我的意思。

Promise.allSettled([randomPromise(1), randomPromise(2), randomPromise(3)]).then(
  function (data) {
    console.log(data);
  }
);

如果三个承诺都成功解决,记录到控制台的data 会是这样的。

[
  { status: "fulfilled", value: 1 },
  { status: "fulfilled", value: 2 },
  { status: "fulfilled", value: 3 }
]

不是说我们现在在我们的then 处理程序中得到status 信息。为什么会这样呢?嗯,这是因为如果任何数量的承诺被拒绝,你需要知道这些信息。通过allSettled ,我们可以让数组中的承诺被拒绝,我们仍然会等待其余的承诺被解决(或拒绝),然后再进入then 处理程序,这时我们会得到所有承诺的信息(即使是被拒绝的)。

让我们看一个例子,其中有两个承诺被拒绝。我们记录到控制台的数据可能看起来像这样。

[
  { status: "rejected", reason: "1 failed randomly!" },
  { status: "fulfilled", value: 2 },
  { status: "rejected", reason: "3 failed randomly!" }
]

结论

如果你的承诺是相关的,以至于你想在其中一个承诺被拒绝时立即跳出,Promise.all 可能适合你。然而,如果你想继续执行其余的承诺,即使其中任何数量的承诺失败了,那么你可能应该使用Promise.allSettled