Promise.any() 原理解析及使用指南
Promise.any(promises)
是 ES2021 新增的特性,它能够并行运行 promise
,并解析为 promises
列表中第一个成功解析的 promise
的值。需要注意的是 Promise.any()
方法依然是实验性的,尚未被所有的浏览器完全支持。
下面来看看 Promise.any()
是如何工作的。
1.工作原理
Promise.any()
可用于以并行和竞争方式执行独立的异步操作,以获取任何第一个完成的 promise
的值。
该函数接受一个 promise
数组(通常为一个可迭代对象)作为参数,如下:
const anyPromise = Promise.any(promises);
当输入 promises
中的第一个 promise
被执行完成时,anyPromise
会立即解析为该 promise
的值。
但是,如果输入数组中的所有 promises
都被拒绝,或者输入数组为空,那么 Promise.any()
会 rejected
包含输入的 promises
执行的 rejection
错误原因集合。
2. 使用指南
现在来深入介绍一下 Promise.any()
, 在这之前,先来定义 2 个简单的函数。
函数
resolveTimeout(value, delay)
将返回一个在经过delay
时间后有resolve
的promise
。
function resolveTimeout(value, delay) { return new Promise((resolve) => setTimeout(() => resolve(value), delay)); }
函数
rejectTimeout(reason, delay)
将返回一个在经过delay
时间后有reject
的promise
。
function rejectTimeout(reason, delay) { return new Promise((r, reject) => setTimeout(() => reject(reason), delay)); }
接下来使用上面定义的 2 个辅助函数来试试 Promise.any()
。
2.1 完成所有 promises
下面尝试运行第一个解析列表:
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)); } const fruits = ["potatoes", "tomatoes"]; const vegetables = ["oranges", "apples"]; const promise = Promise.any([ resolveTimeout(fruits, 1000), resolveTimeout(vegetables, 2000), ]); // 等待... const list = async () => { const result = await promise; console.log(result); }; // 1 秒之后 list(); // ['potatoes', 'tomatoes']
promise .any([…])
返回一个在 1秒内
解析到数组 fruits
的 promise
,因为解析 fruits 的 promise
先执行完成。
第二个是 2秒内
解析到数组 vegetables
的 promise
,其值将被忽略。
2.2 一个 promise
被 rejected
将上面第一个 promise
出现异常被 rejected
,如下代码:
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)); } const vegetables = ["oranges", "apples"]; const promise = Promise.any([ rejectTimeout(new Error("fruits is empty"), 1000), resolveTimeout(vegetables, 2000), ]); // 等待... const list = async () => { const result = await promise; console.log(result); }; // 2 秒之后 list(); // [ 'oranges', 'apples' ]
上面的代码,第一个 promise
在 1秒后
被rejected
,从执行的结果不难看出 Promise.any()
跳过了第一个被rejected
的promise
,等待第二个 2秒后
执行完成的promise
。
2.3 所有的 promises
被 rejected
下面来看下当所有的 promises
被 rejected
会出现什么结果,如下代码:
function rejectTimeout(reason, delay) { return new Promise((r, reject) => setTimeout(() => reject(reason), delay)); } const promise = Promise.any([ rejectTimeout(new Error("fruits is empty"), 1000), rejectTimeout(new Error("vegetables is empty"), 2000), ]); // 等待... const list = async () => { try { const result = await promise; console.log(result); } catch (aggregateError) { console.log(aggregateError); console.log(aggregateError.errors); } }; list(); // [AggregateError: All promises were rejected]
从上面代码的执行结果来看,当所有输入promises
被 rejected
后, Promise.any([...])
将返回一种特殊的错误 AggregateError
而被 rejected
,而详细的 rejected
原因在属性 aggregateError.errors
中 。
总结
Promise.any()
可用于以竞争方式并行执行独立的异步操作,以获取任何第一个成功执行完成的 promise
的值。如果 Promise.any()
的所有输入 promise
都被rejected
后,那么辅助函数返回的 promise
也会以错误集合的方式拒绝,该错误在一个特殊属性 AggregateError
中包含输入 promise
的拒绝原因:aggregateError.errors
。
本文文字及图片出自 InfoQ
你也许感兴趣的:
- 【外评】电脑从哪里获取时间?
- 【外评】为什么 Stack Overflow 正在消失?
- Android 全力押注 Rust,Linux 却在原地踏步?谷歌:用 Rust 重写固件太简单了!
- 【外评】哪些开源项目被广泛使用,但仅由少数人维护?
- 【外评】好的重构与不好的重构
- C 语言老将从中作梗,Rust for Linux 项目内讧升级!核心维护者愤然离职:不受尊重、热情被消耗光
- 【外评】代码审查反模式
- 我受够了维护 AI 生成的代码
- 【外评】Linux 桌面市场份额升至 4.45
- 【外评】作为全栈开发人员如何跟上 AI/ML 的发展?
你对本文的反应是: