Promise.allSettled(),成功与失败都不放过之异步编程演进之 ES11 新特性。

阅读时长 8 分钟读完

如果您已经使用过 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() 方法的基本语法:

其中,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

纠错
反馈