什么是 Promise.allSettled() !新手老手都要会?

什么是 Promise.allSettled() !新手老手都要会?

Promise.allSettled() 方法返回一个在所有给定的 promise 都已经 fulfilled 或 rejected 后的 promise,并带有一个对象数组,每个对象表示对应的 promise 结果。

接着,我们来看看 Promise.allSettled() 是如何工作的。

1. Promise.allSettled()

Promise.allSettled() 可用于并行执行独立的异步操作,并收集这些操作的结果。

该函数接受一个 promise 数组(通常是一个可迭代对象)作为参数:

const statusesPromise = Promise.allSettled(promises);

当所有的输入 promises 都被 fulfilled 或 rejected 时,statusesPromise 会解析为一个具有它们状态的数组

  1. { status: 'fulfilled', value: value } — 如果对应的 promise 已经 fulfilled

  2. 或者 {status: 'rejected', reason: reason} 如果相应的 promise 已经被 rejected

2823245504-60af4dde07f62_fix732.png

在解析所有 promises 之后,可以使用 then 语法提取它们的状态:

statusesPromise.then(statuses => {
 statuses; // [{ status: '...', value: '...' }, ...]
});

或者使用 async/await 语法:

const statuses = await statusesPromise;
statuses; // [{ status: '...', value: '...' }, ...]

2. 取水果和蔬菜

在深入研究 Promise.allSettle() 之前,我们先定义两个简单的 helper 函数。

首先,resolveTimeout(value, delay)返回一个 promise ,该 promise 在经过 delay 时间后用 value 来实现

function resolveTimeout(value, delay) {
  return new Promise(
    resolve => setTimeout(() => resolve(value), delay)
  );
}

第二,rejectTimeout(reason, delay) - 返回一个 promise,在经过 delay 时间后拒绝reason

最后,我们使用这些辅助函数来试验 promise.allsettle()

2.1 All promises fulfilled

我们同时访问当地杂货店的蔬菜和水果。访问每个列表是一个异步操作:

const statusesPromise = Promise.allSettled([
  resolveTimeout(['potatoes', 'tomatoes'], 1000),
  resolveTimeout(['oranges', 'apples'], 1000)
]);
// wait...
const statuses = await statusesPromise;
// after 1 second
console.log(statuses); 
// [
//   { status: 'fulfilled', value: ['potatoes', 'tomatoes'] },
//   { status: 'fulfilled', value: ['oranges', 'apples'] }
// ]

线上事例:codesandbox.io/s/all-resol…

Promise.allSettled([...])返回一个 promise statusesPromise,该 promise 在1秒内解决,就在蔬菜和水果被解决之后,并行地解决。

statusesPromise 解析为一个包含状态的数组。

  1. 数组的第一项包含有蔬菜的已完成状态:status: 'fulfilled', value: ['potatoes', 'tomatoes'] }
  2. 同样的方式,第二项是水果的完成状态: { status: 'fulfilled', value: ['oranges', 'apples'] }

2.2一个 promise 被拒绝

想象一下,在杂货店里已经没有水果了。在这种情况下,我们拒绝水果的 promise。

promise.allsettle() 在这种情况下如何工作?

const statusesPromise = Promise.allSettled([
  resolveTimeout(['potatoes', 'tomatoes'], 1000),
  rejectTimeout(new Error('Out of fruits!'), 1000)
]);
// wait...
const statuses = await statusesPromise;
// after 1 second
console.log(statuses); 
// [
//   { status: 'fulfilled', value: ['potatoes', 'tomatoes'] },
//   { status: 'rejected', reason: Error('Out of fruits!') }
// ]

线上事例:codesandbox.io/s/one-rejec…

Promise.allSettled([...]) 返回的 promise 在 1 秒后解析为一个状态数组:

  1. 数组的第一项,蔬菜 promise 成功解析:{ status: 'fulfilled', value: ['potatoes', 'tomatoes'] }

  2. 第二项,因为水果 promise 被拒绝,所以是一个拒绝状态: { status: 'rejected', reason: Error('Out of fruits') }

即使输入数组中的第二个 promise 被拒绝,statusesPromise仍然会成功解析一个状态数组。

2.3 所有的 promises 都被 rejected

如果杂货店里的蔬菜和水果都卖光了怎么办?在这种情况下,两个 promise 都会被拒绝。

const statusesPromise = Promise.allSettled([
  rejectTimeout(new Error('Out of vegetables!'), 1000),
  rejectTimeout(new Error('Out of fruits!'), 1000)
]);
// wait...
const statuses = await statusesPromise;
// after 1 second
console.log(statuses); 
// [
//   { status: 'rejected', reason: Error('Out of vegetables!')  },
//   { status: 'rejected', reason: Error('Out of fruits!') }
// ]

线上事例:codesandbox.io/s/all-rejec…

在这种情况下,statusesPromise仍然成功地解析为一个状态数组。然而,该数组包含被拒绝的promise 的状态。

3.总结

Promise.allSettled(promises)可以并行地运行 promise,并将状态(fulfilled 或reject)收集到一个聚合数组中。

Promise.allSettled(...)在你需要执行平行和独立的异步操作并收集所有结果时非常有效,即使某些异步操作可能失败。

~~ 完,我是刷碗智,你们的点赞及在看是对我刷碗最大的认可。

编辑中可能存在的bug没法实时知道,事后为了解决这些bug,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug

### JavaScript `Promise.all` vs `Promise.allSettled` #### 定义与行为 `Promise.all` 和 `Promise.allSettled` 均用于处理多个 Promise 实例,但两者的行为存在显著差异。 对于 `Promise.all`,当传入的任意一个 Promise 被拒绝时,整个调用会立即被拒绝并触发 catch 方法中的回调函数[^1]。这使得它适用于所有操作都需要成功的场景。 相反,`Promise.allSettled` 则会在所有的 Promises 结束后(无论是完成还是失败)才会执行 then 中定义的操作,并且不会因为某个 Promise 的失败而提前终止其他 Promise 的执行过程[^2]。因此,在需要知道每一个单独任务的结果而不关心整体是否全部成功的情况下更为适用。 #### 使用示例 ##### 使用 `Promise.all` 下面展示了如何利用 `Promise.all` 来并发运行两个不同的异步任务: ```javascript const promise1 = Promise.resolve('Promise 1 成功'); const promise2 = Promise.reject('Promise 2 失败'); Promise.all([promise1, promise2]) .then((values) => { console.log(values); }) .catch((error) => { console.log('An error occurred in Promise.all():', error); // 输出: An error occurred in Promise.all(): Promise 2 失败 }); ``` 一旦其中一个 Promise 发生错误,则直接进入 `.catch()` 并停止进一步处理剩余的任务。 ##### 使用 `Promise.allSettled` 相比之下,这里有一个例子说明了怎样通过 `Promise.allSettled` 获取一组不同状态下的 Promises 的最终结果: ```javascript mounted() { const promise1 = Promise.resolve(11); const promise2 = new Promise((resolve, reject) => setTimeout(reject, 1000, 'foo0') ); const promise3 = Promise.reject(12); Promise.allSettled([promise1, promise2, promise3]).then((results) => { console.log('results:', results); // 打印每个 Promise 的状态和值 }).catch(err=>{ console.log('err:', err); // 不会被触发 }); } ``` 在这个案例里,即便某些 Promise 出现异常也不会影响到其他的正常工作流程;最后可以得到关于这些 Promises 的完整报告。 #### 总结 - 当希望确保一系列独立但相互依赖的任务都能顺利完成时可以选择 `Promise.all`。 - 若只是想要收集各个子任务的状态信息而不是关注全局的成功与否的话则更适合采用 `Promise.allSettled`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值