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

简介: Promise 对象是 ECMAScript 6 中新增的对象,主要将 JavaScript 中的异步处理对象和处理规则进行了规范化。前面介绍了《Promise.any() 原理解析及使用指南》、《Promise.all() 原理解析及使用指南》和《Promise.allSettled() 原理解析及使用指南》

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 结果(履行或拒绝):image.png


image.png

可以使用 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


相关文章
|
8月前
|
安全 算法 网络协议
解析:HTTPS通过SSL/TLS证书加密的原理与逻辑
HTTPS通过SSL/TLS证书加密,结合对称与非对称加密及数字证书验证实现安全通信。首先,服务器发送含公钥的数字证书,客户端验证其合法性后生成随机数并用公钥加密发送给服务器,双方据此生成相同的对称密钥。后续通信使用对称加密确保高效性和安全性。同时,数字证书验证服务器身份,防止中间人攻击;哈希算法和数字签名确保数据完整性,防止篡改。整个流程保障了身份认证、数据加密和完整性保护。
|
7月前
|
机器学习/深度学习 数据可视化 PyTorch
深入解析图神经网络注意力机制:数学原理与可视化实现
本文深入解析了图神经网络(GNNs)中自注意力机制的内部运作原理,通过可视化和数学推导揭示其工作机制。文章采用“位置-转移图”概念框架,并使用NumPy实现代码示例,逐步拆解自注意力层的计算过程。文中详细展示了从节点特征矩阵、邻接矩阵到生成注意力权重的具体步骤,并通过四个类(GAL1至GAL4)模拟了整个计算流程。最终,结合实际PyTorch Geometric库中的代码,对比分析了核心逻辑,为理解GNN自注意力机制提供了清晰的学习路径。
494 7
深入解析图神经网络注意力机制:数学原理与可视化实现
|
7月前
|
机器学习/深度学习 缓存 自然语言处理
深入解析Tiktokenizer:大语言模型中核心分词技术的原理与架构
Tiktokenizer 是一款现代分词工具,旨在高效、智能地将文本转换为机器可处理的离散单元(token)。它不仅超越了传统的空格分割和正则表达式匹配方法,还结合了上下文感知能力,适应复杂语言结构。Tiktokenizer 的核心特性包括自适应 token 分割、高效编码能力和出色的可扩展性,使其适用于从聊天机器人到大规模文本分析等多种应用场景。通过模块化设计,Tiktokenizer 确保了代码的可重用性和维护性,并在分词精度、处理效率和灵活性方面表现出色。此外,它支持多语言处理、表情符号识别和领域特定文本处理,能够应对各种复杂的文本输入需求。
847 6
深入解析Tiktokenizer:大语言模型中核心分词技术的原理与架构
|
8月前
|
机器学习/深度学习 算法 数据挖掘
解析静态代理IP改善游戏体验的原理
静态代理IP通过提高网络稳定性和降低延迟,优化游戏体验。具体表现在加快游戏网络速度、实时玩家数据分析、优化游戏设计、简化更新流程、维护网络稳定性、提高连接可靠性、支持地区特性及提升访问速度等方面,确保更流畅、高效的游戏体验。
195 22
解析静态代理IP改善游戏体验的原理
|
8月前
|
编解码 缓存 Prometheus
「ximagine」业余爱好者的非专业显示器测试流程规范,同时也是本账号输出内容的数据来源!如何测试显示器?荒岛整理总结出多种测试方法和注意事项,以及粗浅的原理解析!
本期内容为「ximagine」频道《显示器测试流程》的规范及标准,我们主要使用Calman、DisplayCAL、i1Profiler等软件及CA410、Spyder X、i1Pro 2等设备,是我们目前制作内容数据的重要来源,我们深知所做的仍是比较表面的活儿,和工程师、科研人员相比有着不小的差距,测试并不复杂,但是相当繁琐,收集整理测试无不花费大量时间精力,内容不完善或者有错误的地方,希望大佬指出我们好改进!
502 16
「ximagine」业余爱好者的非专业显示器测试流程规范,同时也是本账号输出内容的数据来源!如何测试显示器?荒岛整理总结出多种测试方法和注意事项,以及粗浅的原理解析!
|
7月前
|
传感器 人工智能 监控
反向寻车系统怎么做?基本原理与系统组成解析
本文通过反向寻车系统的核心组成部分与技术分析,阐述反向寻车系统的工作原理,适用于适用于商场停车场、医院停车场及火车站停车场等。如需获取智慧停车场反向寻车技术方案前往文章最下方获取,如有项目合作及技术交流欢迎私信作者。
460 2
|
9月前
|
机器学习/深度学习 自然语言处理 搜索推荐
自注意力机制全解析:从原理到计算细节,一文尽览!
自注意力机制(Self-Attention)最早可追溯至20世纪70年代的神经网络研究,但直到2017年Google Brain团队提出Transformer架构后才广泛应用于深度学习。它通过计算序列内部元素间的相关性,捕捉复杂依赖关系,并支持并行化训练,显著提升了处理长文本和序列数据的能力。相比传统的RNN、LSTM和GRU,自注意力机制在自然语言处理(NLP)、计算机视觉、语音识别及推荐系统等领域展现出卓越性能。其核心步骤包括生成查询(Q)、键(K)和值(V)向量,计算缩放点积注意力得分,应用Softmax归一化,以及加权求和生成输出。自注意力机制提高了模型的表达能力,带来了更精准的服务。
10410 46
|
8月前
|
Java 数据库 开发者
详细介绍SpringBoot启动流程及配置类解析原理
通过对 Spring Boot 启动流程及配置类解析原理的深入分析,我们可以看到 Spring Boot 在启动时的灵活性和可扩展性。理解这些机制不仅有助于开发者更好地使用 Spring Boot 进行应用开发,还能够在面对问题时,迅速定位和解决问题。希望本文能为您在 Spring Boot 开发过程中提供有效的指导和帮助。
825 12
|
8月前
|
开发框架 监控 JavaScript
解锁鸿蒙装饰器:应用、原理与优势全解析
ArkTS提供了多维度的状态管理机制。在UI开发框架中,与UI相关联的数据可以在组件内使用,也可以在不同组件层级间传递,比如父子组件之间、爷孙组件之间,还可以在应用全局范围内传递或跨设备传递。
171 2
|
7月前
|
负载均衡 JavaScript 前端开发
分片上传技术全解析:原理、优势与应用(含简单实现源码)
分片上传通过将大文件分割成多个小的片段或块,然后并行或顺序地上传这些片段,从而提高上传效率和可靠性,特别适用于大文件的上传场景,尤其是在网络环境不佳时,分片上传能有效提高上传体验。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

热门文章

最新文章

推荐镜像

更多
  • DNS