本篇介绍 ES2021 (ES12) 提供的 Promise.any()
和 AggregateError
。
之前有介绍 ES2020 (ES11) 提供的 Promise.allSettled()
,它不会发生短路,也就是都会等所有传入的 Promise settled (即 fulfilled 或 rejected ),而本篇介绍的 Promise.any()
则是会因其中一个传入的 Promise fulfilled 而发生短路。
例如:在 Promise.any()
传入 3 的 Promise,只有第一个会立即 rejected,其余的都会立即 fulfilled:
let promise = Promise.any([
Promise.reject('Oops 1'),
Promise.resolve('OK 1'),
Promise.resolve('OK 2')
]);
可以看到最後回传的 Promise 会 fulfilled,因为 Promise.any()
只要其中一个 Promise fulfilled 就会发生短路,即会立即回传该 Promise fulfilled:
console.log(promise);
// Promise {<fulfilled>: "OK 1"}
若所有传入的 Promise 都 rejected,则会以 AggregateError
rejected,并会保留所有 rejection reasons (即下面范例中的 error.errors
):
Promise.any([
Promise.reject('Oops 1'),
Promise.reject('Oops 2'),
Promise.reject('Oops 3')
])
.catch(error => {
console.log(error instanceof AggregateError);
console.log(error.errors);
console.log(error.message);
console.log(error.stack);
});
// true
// ["Oops 1", "Oops 2", "Oops 3"]
// All promises were rejected
// AggregateError: All promises were rejected
另外,你也可以自行建立新的 AggregateError
物件:
// 语法:AggregateError(errors, message)
new AggregateError([errorA, errorB, errorC], 'error message');
Promise.any()
很适合用在一次处理多个非同步,并且抓出第一个 fulfilled 的 Promise,只有当全部都 rejected 才进行错误处理。
例如:同时发多个 request,看哪一个 endpoint 回应最快,然後把该 endpoint 纪录下来。而且只有当所有 request 都发失败时,才会进行错误处理:
let Base_URL = 'https://jsonplaceholder.typicode.com';
let promises = [
fetch(`${Base_URL}/posts/1`).then(() => 'post'),
fetch(`${Base_URL}/todos/1`).then(() => 'todo'),
fetch(`${Base_URL}/comments/1`).then(() => 'comment')
];
try {
const first = await Promise.any(promises);
console.log(first);
// 纪录 log...
// Logger.log(first);
} catch (error) {
console.log(error.errors);
// 错误处理...
}
另一个适合的情境是你想动态 import 一个模组,但有两个来源可以 import,但你只需 import 最快的那一个即可,此时也很适合用 Promise.any()
:
const lodash = await Promise.any([
import('https://primary.example.com/lodash'),
import('https://secondary.example.com/lodash'),
]);
Promise.any()
| 2ality
<<: NestJs 延伸篇 - Federation 实作
>>: (Day 29) DevOps Challenges
在书写逻辑之前,先厘清程序要达成的需求是什麽? 页面上会有两个组件,一个是登入用,另一个则是用来显示...
导入范围与验证范围差异比较如下: 范围 导入 验证 订定1~4阶程序书 ○ ○ 落实资讯资产资讯蒐集...
SUM() 函数用来计算一数值栏位的总合。用来算金额等数字类型的都很好用~ SUM() 语法 (SQ...
最近依旧忙录,但工作的需要,我还是需要了解新的技术,努力排出时间用在技术研读上,评估一些技术引进的议...
查询资料 query()方法 //查询资料 var number = "" va...