使用 Promise.allSettled 在 Javascript 中等待所有 Promise 解决

阅读时长 7 分钟读完

在编写 Javascript 代码时,我们常常会遇到需要等待多个异步请求全部完成后再进行下一步操作的情况。这时,Promise.all 是我们常用的解决方案,但它有一个缺点:只要其中一个 Promise 被拒绝,就会立即抛出异常,导致其他 Promise 全部终止执行。那么,有没有一种方法能够等待所有 Promise 都执行完毕,并且获取每个 Promise 的执行结果呢?这就是 Promise.allSettled 所能解决的问题。

Promise.allSettled 的基本用法

Promise.allSettled 与 Promise.all 用法相似,都接收一个 Promise 数组作为参数,返回一个新的 Promise 对象。不同的是,Promise.allSettled 不会在任何 Promise 被拒绝时立即拒绝整个 Promise.allSettled,而是会等待所有 Promise 都执行完毕后再返回一个对象数组,每个对象表示一个 Promise 的执行状态,它具有以下结构:

其中,status 表示 Promise 执行的状态,可能的值为 "fulfilled" 或 "rejected";value 是 Promise 执行完毕后的返回值,仅对 "fulfilled" 状态的 Promise 有意义;reason 是 Promise 被拒绝时的拒因,仅对 "rejected" 状态的 Promise 有意义。

下面是一个使用 Promise.allSettled 的简单例子,假设我们需要从三个不同的接口获取数据,获取成功则返回数据,获取失败则返回错误信息:

-- -------------------- ---- -------
----- -------- - ------------------------------------------
    -------------- -- ----------------
    --------- -- ------ -------- ---- ---- ------------

----- -------- - ------------------------------------------
    -------------- -- ----------------
    --------- -- ------ -------- ---- ---- ------------

----- -------- - ------------------------------------------
    -------------- -- ----------------
    --------- -- ------ -------- ---- ---- ------------

----------------------------- --------- ----------------------- -- -
    ---------------------- -- -
        -- -------------- --- ------------ -
            --------------------------
        - ---- -
            -----------------------------
        -
    ---
---

在这个例子中,我们先用 fetch 方法去请求三个不同的接口,并用 then 和 catch 分别处理执行成功和失败的情况,返回一个 Promise 对象。然后,我们将这三个 Promise 对象作为参数传入 Promise.allSettled 方法,并指定一个回调函数,在这个回调函数中依次处理每个 Promise 的执行结果。如果该 Promise 的状态是 "fulfilled",说明它执行成功了,我们就打印它的返回值;如果该 Promise 的状态是 "rejected",说明它执行失败了,我们就打印它的拒因。

使用 Promise.allSettled 进行并行执行和串行执行

除了等待多个接口请求的结果外,Promise.allSettled 还能够用于串行执行和并行执行多个任务的场景。

并行执行多个任务

假设我们想从三个不同的网站上下载大文件,可以使用 Promise.allSettled 来并行执行这三个任务。每个任务返回一个 Promise 对象,表示下载是否成功,我们将这三个 Promise 对象作为参数传入 Promise.allSettled 方法,并在回调函数中处理每个 Promise 对象的执行结果:

-- -------------------- ---- -------
----- -------- - -----------------------------------------------------
----- -------- - -----------------------------------------------------
----- -------- - -----------------------------------------------------

----------------------------- --------- ----------------------- -- -
    ---------------------- -- -
        -- -------------- --- ------------ -
            --------------------- ------------ --------------
        - ---- -
            ----------------------- --------- ---------------
        -
    ---
---

在这个例子中,我们使用 downloadFile 方法从三个不同的网站下载大文件,每个 downloadFile 方法返回一个 Promise 对象,表示下载是否成功。然后,我们将这三个 Promise 对象作为参数传入 Promise.allSettled 方法,并在回调函数中处理每个 Promise 对象的执行结果。

串行执行多个任务

假设我们想按顺序执行多个任务,先执行任务 1,然后执行任务 2,最后执行任务 3。可以使用 Promise.allSettled 来串行执行这三个任务。每个任务返回一个 Promise 对象,表示执行是否成功,我们将这三个 Promise 对象按顺序放在一个数组中,然后使用 Array.prototype.reduce() 方法对这个数组进行串行执行:

-- -------------------- ---- -------
----- ----- - -
    -- -- ----------
    -- -- ----------
    -- -- ---------
--

--------------------------- --------- -- -
    ------ -------------------- -- ----------------------------------
-- ------------------------------- -- -
    ---------------- ----- ---- ---- ------------ ---------
---

在这个例子中,我们先定义了一个数组 tasks,每个元素是一个函数,表示一个要执行的任务。然后,我们使用 Array.prototype.reduce() 方法对这个数组进行串行执行,将每个任务的执行结果作为参数传递给下一个任务。在 reduce 方法的回调函数中,previousTask 表示上一个任务所返回的 Promise 对象,nextTask 表示当前要执行的任务。我们在 previousTask 执行成功后,使用 Promise.allSettled 方法执行下一个任务,并将执行结果再次作为参数传递给下一个任务。最后,我们用 then 方法处理所有任务执行完毕后的结果。

结论

Promise.allSettled 是一个非常有用的方法,可以在 Javascript 中轻松等待所有 Promise 完成,并获取每个 Promise 的执行结果。与 Promise.all 方法不同的是,Promise.allSettled 会在所有 Promise 执行完毕后返回一个对象数组,每个对象表示一个 Promise 的执行状态,即使其中有 Promise 被拒绝也不会立即抛异常,而是会等待所有 Promise 完成后返回执行结果。我们可以利用 Promise.allSettled 解决并行执行和串行执行多个任务的问题,让我们的代码更加简洁和易于维护。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67734a216d66e0f9aae1755c

纠错
反馈