Promise
对象是ECMAScript 6中新增的对象,主要将 JavaScript 中的异步处理对象和处理规则进行了规范化。前面介绍了《Promise.any() 原理解析及使用指南》和《Promise.all() 原理解析及使用指南》,本文继续来介绍 Promise
另一个方法 Promise.allSettled(promises)
,返回一个在所有给定的 promise
都已经 fulfilled
或 rejected
后的 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()
返回的一个 promise
的 resolve
状态数组是按照执行前 statusesPromise
的顺序组成其结果。
2.2 一个 promise
被 rejected
将上面第一个 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') }]
即使输入数组中的第二个 promise
被 rejected
, statusesPromise
仍然可以成功解析状态数组。
2.3 所有 promises
被 rejected
将上面所有的 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()
就是不错的选择,即使一些异步操作可能失败。