如何使用Promise.any() 2021-11-16 默认分类 暂无评论 3887 次阅读 ![WeCom20211116-123806.png](http://www.guobacai.com/usr/uploads/2021/11/1161251262.png) Promise.any(promises)是一个辅助函数,它可以并行地运行promises并解析到promises列表中第一个成功解析的promises的值。 让我们看看Promise.any()如何工作。 # 1. Promise.any() Promise.any()对于以并行和竞赛的方式执行独立的异步操作非常有用,可以获得任何第一个被履行的承诺的值。 该函数接受一个数组(或一般是一个可迭代的)的承诺作为参数。 const anyPromise = Promise.any(promises)。 当输入的承诺中的任何第一个承诺被实现时,anyPromise会立即解析为该承诺的值。 ![WeCom20211116-123921.png](http://www.guobacai.com/usr/uploads/2021/11/4181944768.png) 你可以使用then-able语法提取第一个承诺的值。 ``` anyPromise.then(firstValue => { firstValue; // The value of the first fulfilled promise }); ``` 或使用async/await语法。 ``` const firstValue = await anyPromise; firstValue; // The value of the first fulfilled promise ``` Promise.any()返回的承诺与任何第一个履行的承诺一起履行。即使有些承诺被拒绝,这些拒绝也会被忽略。 ![WeCom20211116-124151.png](http://www.guobacai.com/usr/uploads/2021/11/1292948982.png) 然而,如果输入数组中的所有承诺都被拒绝,或者输入数组是空的,那么Promise.any()就会拒绝,并给出一个包含输入承诺的所有拒绝原因的聚合错误。 ![WeCom20211116-124217.png](http://www.guobacai.com/usr/uploads/2021/11/1372416983.png) ## 2. Fruits and vegetables 在深入研究Promise.any()之前,让我们定义两个简单的辅助函数。 首先,resolveTimeout(value, delay) - 返回一个在通过延迟时间后以值实现的承诺。 ``` function resolveTimeout(value, delay) { return new Promise( resolve => setTimeout(() => resolve(value), delay) ); } ``` 第二,rejectTimeout(reason, delay) - 返回一个承诺,在通过延迟时间后拒绝原因。 ``` function rejectTimeout(reason, delay) { return new Promise( (r, reject) => setTimeout(() => reject(reason), delay) ); } ``` 让我们用这些辅助函数在Promise.any()上做实验。 ### 2.1 所有 promises 被执行 让我们试着从local grocery store获取第一个解决的清单。 ``` const promise = Promise.any([ resolveTimeout(['potatoes', 'tomatoes'], 1000), resolveTimeout(['oranges', 'apples'], 2000) ]); // wait... const list = await promise; // after 1 second console.log(list); // logs ['potatoes', 'tomatoes'] ``` Promise.any([...])返回一个promise,该promise在1秒内解析为vegetables列表['potatoes', 'tomatoes']。所有这些都是因为vegetables promise首先实现了。 第二个promise,即fruits列表,在2秒内解决,但它的值被忽略了。 ### 2.2 一个promise rejected 想象一下,在杂货店里已经没有蔬菜了。在这种情况下,让我们拒绝蔬菜的promise。 在这种情况下,Promise.any()将如何工作? ``` const promise = Promise.any([ rejectTimeout(new Error("Out of vegetables!"), 1000), resolveTimeout(["oranges", "apples"], 2000) ]); // wait... const list = await promise; // after 2 seconds console.log(list); // logs ['oranges', 'apples'] ``` 这种情况有点棘手。 首先,蔬菜的承诺在1秒后被拒绝。然而,Promise.any()跳过了这个拒绝,仍然在等待查看fruits promise的状态。 最后,又过了一秒,fruits promise解析为一个水果列表['oranges', 'apples']。马上,由Promise.any([...])返回的promise也解析为这个值。 ### 2.3 所有的promises rejected 如果杂货店里的vegetables和 fruits都卖光了怎么办?在这种情况下,两个promises都被拒绝。 ``` const promise = Promise.any([ rejectTimeout(new Error('Out of vegetables!'), 1000), rejectTimeout(new Error('Out of fruits!'), 2000) ]); try { // wait... const list = await promise; } catch (aggregateError) { console.log(aggregateError); // logs AggregateError console.log(aggregateError.errors); // logs [Error('Out of vegetables!'), Error('Out of fruits!')] } ``` 所有的输入promises都被拒绝。因此,由Promise.any([...])返回的promises也会被rejected,并带有一种特殊的错误--AggregateError--它包含输入promises的rejected原因。 聚合错误提供了一个特殊的属性 errors: 它是一个数组,包含被rejected的输入promises的错误。 # 3. 总结 Promise.any()对于以竞赛的方式并行执行独立的异步操作是非常有用的,可以获得任何第一个成功解决的promise的值。 如果Promise.any()的所有输入promise都被拒绝了,那么由辅助函数返回的promise也会被rejected,并带有一个聚合错误,该错误包含了输入承诺在一个特殊属性中的拒绝原因:aggregateError.errors。 请注意,如果输入数组为空,Promise.any([])也会拒绝。 标签: value, const, 函数, promises, firstvalue, anypromise, 承诺, await
评论已关闭