如果您已经使用过 Promise.all(),您可能知道仅当所有承诺都成功时,它才会成功。 如果有任何一个承诺失败,该方法便会立即返回一个拒绝的 Promise 对象。 当我们需要同时执行多个异步操作,Promise.all() 是非常有用的方法。
但是,当这些异步操作中的一些可能失败,我们需要更多的信息来处理它。 Promise.allSettled() 引入了这个新的特性,在 Promise 中,在成功或失败之间查看所有承诺的完整状态。
Promise.allSettled() 是什么?
Promise.allSettled() 是 ECMAScript 2020 新增的 Promise API 之一,用于响应并发异步操作,不管它们成功还是失败。与 Promise.all() 不同的是,Promise.allSettled() 忽略所有承诺的拒绝并等待它们所有最终状态都解决。
该方法返回一个承诺,其成功值是一个包含每个承诺的对象数组,每个对象都有两个属性:
status
:可为 "fulfilled" 、"rejected" 或 "pending" 三个值之一,表示解决状态。value
:对于status
是 "fulfilled" 的对象,它包含原始解决值。 对于status
是 "rejected" 的对象,它包含拒绝原因。
以下是 Promise.allSettled() 方法的基本语法:
Promise.allSettled(iterable);
其中,iterable
参数可以是一个数组、一个类数组对象或一个可迭代对象。 它包含一组异步操作,并返回一个承诺,该承诺将解决为数组,其中包含每个异步操作的结果对象。
为什么使用 Promise.allSettled()?
在并发执行许多异步操作的情况下,我们可能只对某些操作失败或成功感兴趣。 使用 Promise.all() 不足以解决这个问题,因为它只返回失败或成功的数据。 例如,在收集列表的同时,获取多个 API 是否成功不应该放弃整个列表的构建。
-- -------------------- ---- ------- ----- -------- - - ------------ ------------ ------------ -- --------------------- ------------ -- - -- ---- -- -------------- -- - -- -------------------- ---
上面的代码检索了 URL 后,将它们合并,如果一个 url 返回错误,整个数据就失去了。因此,使用 Promise.allSettled() 能够让我们知道每一个 URL 方案,而不会只是放弃它们的结果。
-- -------------------- ---- ------- ----- -------- - - ------------ ------------ ------------ -- ---------------------------- -- ---------- -- -- ------ ------------ ------ ---- ----- --------------- -- - ----- -------- - ----------------- ------ -- -- ------ --- ------------ ----- --------- - ----------------- ------ -- -- ------ --- ------------- ------------- --------- --------- --- ---
上面的代码处理了每个 url 及其返回状态,filter() 和 map() 操作会返回成功值 or 拒绝的值。当我们需要同时执行多个异步操作时,Promise.allSettled() 非常有用。
Promise.allSettled() 与 Promise.all() 的异同
Promise.all() 要求每个异步操作成功才能成功,否则拒绝。 因此,如果其中一个承诺被拒绝,则整个 Promise.all() 将被拒绝。 请参阅下面的示例:
-- -------------------- ---- ------- -- --------------------- ----- -------- - -------------------- ------------------- -------------------- --------------------- -------------- -- - -------------------- -- --- --- -- -- -- -------------- -- - --------------------- --- -- ------------ ------- ---- ----- -------- - -------------------- ------------------------ -------------------- --------------------- -------------- -- - -------------------- -- ---- ---- --- ----- -- -------------- -- - --------------------- -- --- ----- ---
相反,Promise.allSettled() 将考虑所有 Promise,而不管它们成功或失败。
-- -------------------- ---- ------- ----- -------- - - ------------------- ------------------ ------------------- -- ---------------------------- --------------- -- - --------------------- -- - -- - ------- ------------ ------ - -- -- - ------- ----------- ------- - -- -- - ------- ------------ ------ - -- -- - -- ----------------------
注意:无论承诺是否被拒绝,它们都被视为 Settled,我们可以对其进行报告。
最佳实践:使用 Promise.allSettled() 以避免未捕获的异常
在 Node.js 中,未捕获的异常会导致进程崩溃。 如果您正在编写具有许多并发异步操作的 Node.js 代码,未处理的异步异常会使代码变得更加危险。 您的代码可能会崩溃,而您可能甚至不知道如何调查和修复此问题。
在这种情况下,Promise.allSettled() 可以很好地帮助我们避免未处理的异步异常。 让我们看看下面的代码片段:
-- -------------------- ---- ------- ----- -------- - ------------ ----------- ------------ ------------------------------------------- -- - ------------------------ -- -- - -- -------------- --- ----------- - ---------------------- ---- ------ ---- ------ ------------------- - --- ---
使用 Promise.allSettled(),任何异常均被 Promise.catch() 捕获,再也没有未捕获的异常了。 最终状态数组将是 Promise 执行结果,因此我们不需要处理单独的拒绝处理程序,未处理异常也不会崩溃我们的代码。
结论
ES11 中的 Promise.allSettled() 引入了一个很好用的功能,允许我们在所有 Promise 执行完成后快速检查他们的状态,处理 Promise 失败而不抛出错误,这在处理请求数据时非常有用。
这篇文章讲解了 Promise.allSettled(),并与 Promise.all() 进行比较,陈述了 Promise.allSettled() 的优点和最佳实践,希望能为学习和使用 Promise.allSettled() 的开发人员提供帮助。
相关阅读
示例代码:
-- -------------------- ---- ------- ----- -------- - - ------------------- ------------------ ------------------- -- ---------------------------- --------------- -- - --------------------- -- - -- - ------- ------------ ------ - -- -- - ------- ----------- ------- - -- -- - ------- ------------ ------ - -- -- - -- ----------------------
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/676ffc2fe9a7045d0d78ee87