写点什么

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

用户头像
devpoint
关注
发布于: 1 小时前
Promise.race() 原理解析及使用指南

Promise 对象是 ECMAScript 6 中新增的对象,主要将 JavaScript 中的异步处理对象和处理规则进行了规范化。前面介绍了《Promise.any() 原理解析及使用指南》、《Promise.all() 原理解析及使用指南》和《Promise.allSettled() 原理解析及使用指南》,本文继续来介绍 Promise 另一个方法 Promise.race(promises) ,顾名思义就是赛跑的意思,Promise.race([p1, p2, p3]) 里面 promise 数组那个执行完成得快就获取那个的结果,不管结果本身是成功履行状态还是失败拒绝状态,只输出最快的 promise


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

1.工作原理

Promise.race() 返回一个 promise,一旦迭代器中的某个 promise 履行或拒绝,返回的 promise 就会履行或拒绝。


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


const racePromise = Promise.race(promises);
复制代码


当所有输入 promises 中有一个 promise 快速被履行或拒绝时,racePromise 就会解析快速完成的 promise 结果(履行或拒绝):




可以使用 then 方法提取 racePromise 的结果:


racePromise.then((fastValue) => {    fastValue // 快速完成的 promise});
复制代码


也可以使用 async/await 语法:


const fastPromise = await racePromise;
fastPromise; // 快速完成的 promise
复制代码


Promise.race() 返回的承诺和最先完成的承诺信息一致。


Promise.race()Promise.any() 的不同:Promise.race() 承诺列表中寻找第一个履行或拒绝的承诺;Promise.any() 是从承诺列表中查找第一个履行的承诺。

2. 使用指南

现在来深入介绍 Promise.race() 的使用之前,同样先来定义 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.race()

2.1 完成所有 promises

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


const fruits = ["potatoes", "tomatoes"];const vegetables = ["oranges", "apples"];
const racePromise = Promise.race([ resolveTimeout(fruits, 5000), resolveTimeout(vegetables, 1000),]);
// 等待 1 秒 ...const list = async () => { try { const fastPromise = await racePromise; console.log(fastPromise); } catch (error) { console.log(error); }};
list(); // [ 'oranges', 'apples' ]
复制代码


从上面执行的结果来看 Promise.race() 返回最快履行的 promiseresolve 结果。

2.2 一个 promiserejected

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


const fruits = ["potatoes", "tomatoes"];
const racePromise = Promise.race([ resolveTimeout(fruits, 2000), rejectTimeout(new Error("Vegetables is empty"), 1000),]);
// 等待 1 秒 ...const list = async () => { try { const fastPromise = await racePromise; console.log(fastPromise); } catch (error) { console.log(error); }};
list(); // Error: Vegetables is empty
复制代码


从上面的结果看,最先完成的 promiserejected ,那么 fastPromise 返回的 promise 也是被 rejected


下面将rejected 的承诺时间延长到 5 秒,如下:


const fruits = ["potatoes", "tomatoes"];
const racePromise = Promise.race([ resolveTimeout(fruits, 2000), rejectTimeout(new Error("Vegetables is empty"), 5000),]);
// 等待 2 秒 ...const list = async () => { try { const fastPromise = await racePromise; console.log(fastPromise); } catch (error) { console.log(error); }};
list(); // [ 'potatoes', 'tomatoes' ]
复制代码


从上面执行结果看到,最快完成的 promise 履行了 resolve ,那么 fastPromise 返回的 promise 也是履行了 resolve

2.3 所有 promisesrejected

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


const racePromise = Promise.race([    rejectTimeout(new Error("Fruits is empty"), 2000),    rejectTimeout(new Error("Vegetables is empty"), 1000),]);
// 等待 1 秒 ...const list = async () => { try { const fastPromise = await racePromise; console.log(fastPromise); } catch (error) { console.log(error); }};
list(); // Error: Vegetables is empty
复制代码


从结果来看,虽然两个承诺都被拒绝了,fastPromise 返回的 promise 是最快被拒绝的 。

3. 使用场景

3.1. 性能测试

在有异步操作的项目中,在对于网络或数据库请求进行性能进行优化的时候,可以使用 Promises 来测试其优化效果,通过使用 Promise.race() 来测试两种不同的方法的响应速度。

3.2 最佳选择

例如获取同一类型的数据有多个请求服务器,同时向多个服务器发送请求,只要其中一个完成工作,就将其数据呈现,达到选择最佳线路的效果。这是可以使用 Promise.race() 同时执行 promise 并在第一个成功后立即完成。

总结

文章介绍了 Promise.race() 原理和使用,另外增加了 2 个可能用得到的场景,而Promise.race()Promise.any() 之间的基本区别在于,Promise.race() 为第一个已解决和已拒绝的 promise 执行回调函数,而 Promise.any() 为第一个已履行的 promise 执行回调函数,如果没有履行的 promise 则拒绝一个特殊属性 AggregateError

发布于: 1 小时前阅读数: 2
用户头像

devpoint

关注

细节的追求者 2011.11.12 加入

专注前端开发,用技术创造价值!

评论

发布
暂无评论
Promise.race() 原理解析及使用指南