6

Promise.allSettled() 原理解析及使用指南

 3 years ago
source link: https://my.oschina.net/lav/blog/5229388
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Promise 对象是ECMAScript 6中新增的对象,主要将 JavaScript 中的异步处理对象和处理规则进行了规范化。前面介绍了《Promise.any() 原理解析及使用指南》和《Promise.all() 原理解析及使用指南》,本文继续来介绍 Promise 另一个方法 Promise.allSettled(promises) ,返回一个在所有给定的 promise 都已经 fulfilledrejected 后的 promise ,并带有一个对象数组,每个对象表示对应的promise 结果。

下面来看看 Promise.allSettled() 是如何工作的。

1.工作原理

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

函数接受一个 promise 数组(或通常是一个可迭代的)作为参数,如下:

const statusesPromise = Promise.allSettled(promises);

当所有输入 promises 都被履行或拒绝时,statusesPromise 会解析为一个具有其状态的数组:

  • { status: 'fulfilled', value:value } : 如果相应的 promise 已经履行
  • { status: 'rejected', reason: reason } :如果相应的 promise 被拒绝

可以使用 then 方法提取所有 promises 的状态:

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

也可以使用 async/await 语法:

const statuses = await statusesPromise;

statuses; // [{ status: '...', value: '...' }, ...]

Promise.allSettled() 返回的承诺总是以一系列状态实现,无论是否有一些(或者全部)输入承诺被拒绝。

Promise.allSettled()Promise.all() 的最大不同:Promise.allSettled() 永远不会被 rejected

2. 使用指南

现在来深入介绍 Promise.allSettled() 的使用之前, 还是先来定义 2 个简单的函数。

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

接下来使用上面定义的2个辅助函数来试试 Promise.allSettled()

2.1 完成所有 promises

下面定义了一个 promise 数组 statusesPromise ,所有的 promise 都能够成功的 resolve 值,如下:

const fruits = ["potatoes", "tomatoes"];
const vegetables = ["oranges", "apples"];

const statusesPromise = Promise.allSettled([
    resolveTimeout(fruits, 2000),
    resolveTimeout(vegetables, 1000),
]);

// 等待 2 秒 ...
const list = async () => {
    try {
        const statuses = await statusesPromise;
        console.log(statuses);
    } catch (error) {
        console.log(error);
    }
};

list(); // [{ status: 'fulfilled', value: [ 'potatoes', 'tomatoes' ] },{ status: 'fulfilled', value: [ 'oranges', 'apples' ] }]

从上面执行的结果来看 Promise.allSettled() 返回的一个 promiseresolve 状态数组是按照执行前 statusesPromise 的顺序组成其结果。

2.2 一个 promiserejected

将上面第一个 promise 出现异常被 rejected ,如下代码:

const fruits = ["potatoes", "tomatoes"];

const statusesPromise = Promise.allSettled([
    resolveTimeout(fruits, 2000),
    rejectTimeout(new Error("Vegetables is empty"), 1000),
]);

// 等待 2 秒 ...
const list = async () => {
    try {
        const statuses = await statusesPromise;
        console.log(statuses);
    } catch (error) {
        console.log(error);
    }
};

list(); // // [{ status: 'fulfilled', value: ['potatoes', 'tomatoes'] },{ status: 'rejected', reason: Error('Vegetables is empty') }]

即使输入数组中的第二个 promiserejectedstatusesPromise 仍然可以成功解析状态数组。

2.3 所有 promisesrejected

将上面所有的 promises 出现异常被 rejected ,如下代码:

const statusesPromise = Promise.allSettled([
    rejectTimeout(new Error("Fruits is empty"), 2000),
    rejectTimeout(new Error("Vegetables is empty"), 1000),
]);

// 等待 2 秒 ...
const list = async () => {
    try {
        const statuses = await statusesPromise;
        console.log(statuses);
    } catch (error) {
        console.log(error);
    }
};

list(); // // [{ status: 'rejected', reason: Error('Fruits is empty') },{ status: 'rejected', reason: Error('Vegetables is empty') }]

当需要执行并行和独立的异步操作并收集所有结果时,Promise.allSettled() 就是不错的选择,即使一些异步操作可能失败。


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK