promise.race用于返回首个完成的promise结果,核心是“快”和“及时响应”,适用于超时控制、多源竞速、用户交互优先及服务健康探测等场景。

Promise.race 用于“谁先完成谁说了算”,不管成功还是失败,只要数组里任意一个 Promise 状态改变(fulfilled 或 rejected),就立刻结束并返回那个结果。它不等其他,也不汇总,核心是“快”和“及时响应”。
超时控制:防止请求卡死
网络请求可能因网络差、服务宕机等原因迟迟不返回,用 Promise.race 可主动设限,避免页面假死或用户长时间等待。
- 构造一个正常请求 Promise 和一个定时 reject 的超时 Promise
- 两者 race,谁先触发谁生效:请求快则得数据;超时快则报错
- 配合 AbortController 更健壮(能真正中断 fetch),但仅用 setTimeout + reject 已能满足多数场景
示例:
const fetchWithTimeout = (url, ms) => {const req = fetch(url);
const timeout = new Promise((_, reject) =>
setTimeout(() => reject(new Error('请求超时')), ms)
);
return Promise.race([req, timeout]);
};
多源竞速:选最快的数据源
当多个接口提供相同内容(如主站 + CDN + 备份服务),可用 race 获取首个响应,提升首屏速度或容灾能力。
- 常见于图片加载、静态资源获取、A/B 测试接口、镜像 API 调用
- 注意:失败的请求不会影响 race 结果,但若全部失败,则整体 reject
- 建议搭配错误兜底(如 .catch 后 fallback 到默认值或重试)
示例(加载图片):
const loadFastestImage = (urls) =>Promise.race(urls.map(url =>
new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(url);
img.onerror = () => reject();
img.src = url;
})
));
用户交互优先:响应最早的操作意图
在需要“以用户动作为准”的场景中,race 可协调异步任务与手动干预(如取消、跳过、确认)。
- 例如:上传中允许点击“跳过”,用 race 包裹上传 Promise 和“跳过点击事件 Promise”
- 又如:动画播放时监听用户暂停操作,哪个先发生就执行对应逻辑
- 关键点:把同步行为(如 click)包装成 Promise(例如用 Promise.resolve() + 事件监听器)
服务健康探测:快速判断可用性
启动时或切换前,向多个服务地址发起轻量探测(如 HEAD 请求),用 race 拿到第一个成功响应的服务,作为当前可用节点。
- 比轮询更高效,避免等待慢节点拖累整体初始化
- 适合网关选路、微服务实例发现、CDN 节点自动切换
- 注意区分“连接成功”和“业务可用”,必要时叠加简单校验(如检查 status === 200)











