Promise.all 和 是在JavaScript中处理承诺数组的两种不同方式。让我们来比较一下它们,并谈谈什么时候使用这两种方法比较合适。Promise.allSettled
它们如何相似
Promise.all 和Promise.allSettled 的主要相似之处是,这两个方法都以一个承诺数组作为参数。你使用它们是因为你有一组你想在继续前进之前处理的承诺。不过这也是相似之处的结束。正如我们将看到的,这些方法实际处理承诺的方式是非常不同的。
最大的区别 处理拒绝
处理拒绝是Promise.all 和Promise.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 。