什么时候使用Promise.allSettled

366 阅读1分钟
// 结果resolved的promise实例
const success = (ms, msg )=> new Promise(res => setTimeout(() => res(msg), ms));
// 结果rejected的promise实例
const fail = (ms, msg) => new Promise((res, rej)=>setTimeout(() => rej(msg), ms));
Promise.all([success(2000, "success_1"), success(1000, "success_2")]).then(console.log)
// ["success_1", "success_2"]
Promise.all([
    success(2000, "success_1"),
    success(1000, "success_2"),
    fail(3000, "fail_1"),
    fail(4000, "fail_2"),
])
  .then(console.info)
  .catch(console.error)
// "fail_1" 仅输出了 "fail_1", fail(4000, "fail_2")函数未执行

all接收的promise实例全部resolved之后结果被then捕获,promise.all的状态变成resolved,一旦有一个实例A的状态转为rejected,那promise.all的状态变成rejected,此时的catch捕获A的reject信息。

再看 Promise.allSettled

Promise.allSettled([
    success(2000, "success_1"),
    success(1000, "success_2")
])
  .then(console.info)
  .catch(console.error)
/*
[{status: "fulfilled", value: "success_1"},
{status: "fulfilled", value: "success_2"}]
*/
Promise.allSettled([
    fail(3000, "fail_1"),
    fail(4000, "fail_2"),
])
  .then(console.info)
  .catch(console.error)
/*
[{status: "rejected", reason: "fail_1"},
{status: "rejected", reason: "fail_2"}]
*/
Promise.allSettled([
    success(2000, "success_1"),
    success(1000, "success_2"),
    fail(3000, "fail_1"),
    fail(4000, "fail_2"),
])
  .then(console.info)
  .catch(console.error)
/*
[{status: "fulfilled", value: "success_1"},
{status: "fulfilled", value: "success_2"},
{status: "rejected", reason: "fail_1"},
{status: "rejected", reason: "fail_2"}]
*/

allSettled接收的所有Promise实例的状态都转变成resolved或者rejected时,then 直接捕获了最终的结果,用数组包裹。所以上面的catch语句都可以去掉。

相比较来说,Promise.all 适合promise 实例相互依赖场景,因为状态(resolved)的转变依赖所有的实例。

Promise.allSettled 适合需要知道所有实例状态的场景,特别是实例rejected的状态。

下面来验证下在Promise.all中,一个实例rejected之后其他实例还会不会执行。

const fail1 = (ms, msg) => new Promise((res, rej)=>setTimeout(() => {
    rej(msg);
    console.log("run");
}, ms));

Promise.all([
    fail1(1000, "fail_1"),
    fail1(2000, "fail_2"),
    fail1(2000, "fail_2"),
    fail1(2000, "fail_2"),
])
  .then(console.info)
  .catch(console.error)

当然会执行,只是catch只会捕获首次抛出的错误。