JS中Promise.all()和Promise.allSettled()的区别是什么?

114
我正在阅读 MDN 上有关 Promise 的手册,并发现了这两种方法,它们对我来说似乎是相似的: 它们都接收一个 iterable 对象,并返回一个包含已完成的 Promise 的数组。
那么,它们之间有什么区别呢?

2
all 用于执行已经 resolved 的 promises,而 allSettled 则是任何已完成的 - 包括 resolved 和 rejected。每篇文章的第一句话都概述了这种差异。 - VLAZ
1
@Raymond 你参考的是哪个网站? - ezio4df
1
它们都不会返回一个数组,而是返回一个可能解析为数组的 Promise……但在 .all 的情况下,返回的 Promise 并不总是解析为数组——这就在文档的第一行中说明了——实际上,阅读你链接的每个文档的第一段,你就能得到答案。 - Jaromanda X
1
感谢大家,我已经得到了答案。从现在开始,我会更加专注地阅读手册。 - ezio4df
4个回答

199
Promise.all会在数组中有任意一个Promise被拒绝时立即拒绝。 Promise.allSettled永远不会拒绝 - 它将在数组中的所有Promise都被拒绝或解决后解决。
它们的解决值也不同。 Promise.all将解决为每个Promise解决的值的数组 - 例如[Promise.resolve(1), Promise.resolve(2)]将变成[1, 2]Promise.allSettled将给出[{ status: 'fulfilled', value: 1 }, { status: 'fulfilled',value: 2 }]

Promise.all([Promise.resolve(1), Promise.resolve(2)])
  .then(console.log);
Promise.allSettled([Promise.resolve(1), Promise.resolve(2)])
  .then(console.log);
如果 Promise.all 中有一个 Promise 被拒绝,Promise.all 将会以该拒绝值来拒绝,但是 Promise.allSettled 会以 { status: 'rejected', reason: <error> } 的对象形式在数组中的位置处进行解决。
Promise.all([Promise.reject(1), Promise.resolve(2)])
  .catch((err) => {
    console.log('err', err);
  });
Promise.allSettled([Promise.reject(1), Promise.resolve(2)])
  .then(console.log);


30

Promise.all: 当传递给它的所有promise(作为数组)都被解决时,它才会解决,否则它将拒绝并返回第一个被拒绝的promise的错误。

Promise.allSettled: 这个方法总是会解决,并返回一个包含有关已解决和已拒绝promise的信息的数组。请仔细查看结果数组的属性(状态、值和原因)。

示例1:

const pms1 = Promise.resolve(1);
// setTimeout(function, milliseconds, param1, param2, ...)
const pms2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 200, 2);
});
const pms3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 3);
});
const pmsAry = [pms1, pms2, pms3];

Promise.all(pmsAry)
  .then(resAry => console.log(resAry)) // resAry order is same as pmsAry order
  .catch(error => console.log(error));

/* 
 * Note here we are not writing 'catch' because Promise.allSettled ALWAYS RESOLVES
 * with array containing information about resolved or rejected promises
 */
Promise.allSettled(pmsAry)
.then(resAry => console.log(resAry)); // resAry order is same as pmsAry order

输出:

[1, 2, 3] 
// Promise.all output ORDER doesn't depend on promise resolution time

[{ status: "fulfilled", value: 1 },
 { status: "fulfilled", value: 2 }, 
 { status: "fulfilled", value: 3 }]
// Promise.allSettled output ORDER doesn't depend on promise resolution time

示例2:

const pms1 = Promise.resolve(1);
const pms2 = new Promise((resolve, reject) => {
  setTimeout(reject, 200, '200ms Err');
});
const pms3 = new Promise((resolve, reject) => {
  setTimeout(reject, 100, '100ms Err');
});
const pmsAry = [pms1, pms2, pms3];

Promise.all(pmsAry)
  .then(resAry => console.log(resAry))
  .catch(error => console.log(error));

Promise.allSettled(pmsAry)
  .then(resAry => console.log(resAry));

输出:

100ms Err
/* 
 * Note: Here there are TWO promises which are getting REJECTED but output is
 * ONLY ONE (i.e the one which is getting rejected FIRST) 
 */

[{ status: "fulfilled", value: 1 },             // Note: value
 { status: "rejected", reason: "200ms Err" },   
 { status: "rejected", reason: "100ms Err" }]   // Note: reason

8
当您想确保使用的操作应该全部解决或成功的承诺时,需要使用Promise.all,因为它在每个承诺被解决后完成。
但是当您只想完成所有承诺,无论它们是否解决或拒绝,则使用Promise.allSettled
它们都以批量执行承诺,但微妙的差异在于它们处理承诺迭代的方式。

“微妙的区别在于它们处理承诺迭代的方式”,这是否意味着在 allSettled 中执行顺序不是同时的?例如,先执行 promise1,然后执行 promise2,然后执行 promise3等等... - Got To Figure
@GotToFigure 有点晚了,但如果有人来到这里,这就是你可以找到答案的地方:https://dev59.com/z10Z5IYBdhLWcg3w_0h8 - Juljo Shahini

4

Promise.all : 它返回一个 Promise 对象,当数组中所有 Promise 对象都解决(resolve)时解决,如果其中有一个或多个 Promise 被拒绝(reject),则被拒绝。


Promise.allSettled : 它返回一个 Promise 对象,当数组中所有的 Promise 对象都已被解决(已拒绝或已解决)时解决。


Note : 两者都接受一个可迭代对象,并返回一个包含已完成 Promises 的数组。

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接