前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库Promise.any vs race
JavaScript异步与 Promise

Promise.any 和 Promise.race 都是取最快的,区别在哪?

Promise.race 看谁先结束,第一个结束的是失败,它就直接失败。Promise.any 看谁先成功,失败的会被跳过,只有全部失败才以 AggregateError 拒绝。

前端进阶之旅 · 一题精讲更新于 2026.09.29
JavaScript#异步与 Promise#异步编程
先看核心答案读代码示例
理解线索

比的是先结束还是先成功

  1. Promise.race第一个敲定的结果直接拿来用,失败也照单全收
  2. Promise.any等第一个成功,中途的失败不影响结果
  3. AggregateErrorany 全部失败时的拒绝值,原因都在 errors 里

两者都不会取消剩下的 Promise。结果已经定了,其他请求还在跑,要真正停下来得配合 AbortController。

核心回答

先记住这个答案

两者都是「谁快用谁」,区别在于怎么算快。Promise.race 看谁先结束,第一个结束的不管是成功还是失败,结果都直接采用。Promise.any 看谁先成功,中途失败的会被跳过,只要有一个成功就兑现;全部失败时才拒绝,拒绝值是 AggregateError。所以做超时控制用 race,从几个备用源里取一个能用的用 any。

  • race 取第一个结束的,成功失败都算
  • any 取第一个成功的,失败直接跳过
  • race 适合做超时,any 适合多节点择优
  • 传空数组:race 永远 pending,any 立刻拒绝

同一组任务,两种结果

假设有两个节点:A 在 50 毫秒时失败,B 在 100 毫秒时成功。分别交给 race 和 any,看看拿到的是什么。

先失败后成功的两个节点JavaScript
const delay = (ms, ok, v) =>
  new Promise((resolve, reject) => setTimeout(() => (ok ? resolve(v) : reject(new Error(v))), ms))

// 每次调用都生成一组新任务:A 50ms 失败,B 100ms 成功
const tasks = () => [delay(50, false, '节点A失败'), delay(100, true, '节点B成功')]

Promise.race(tasks()).then(
  (v) => console.log('race 成功:', v),
  (e) => console.log('race 失败:', e.message) // A 先结束,直接失败
)
Promise.any(tasks()).then(
  (v) => console.log('any 成功:', v), // 跳过 A,等到 B
  (e) => console.log('any 失败:', e.message)
)
查看输出与解释
race 失败: 节点A失败
any 成功: 节点B成功

50 毫秒时 A 失败,race 立刻以这个错误拒绝,后面 B 成功了它也不管。any 把 A 的失败记下来继续等,100 毫秒时 B 成功,于是兑现为 B 的值。 可以这样记:race 是短跑比赛,第一个冲线的就是结果,哪怕他是摔着过线的;any 是找工作投简历,被拒几家没关系,拿到一个 offer 就算成功。

各自最适合的场景

两个 API 的差别决定了它们解决的是完全不同的问题,很少能互相替换。

race 做超时控制
把真实请求和一个定时拒绝的 Promise 放在一起比:Promise.race([request, timeout(3000)]),其中 timeout 是自己用 new Promise 包 setTimeout 写的小函数,到点就 reject。请求先回来就用请求的结果;3 秒还没回来,定时器先拒绝,整体就以超时错误失败。这里恰恰需要「失败也算结束」,换成 any 反而不行,超时的拒绝会被跳过,还得继续等请求。 如果请求本身支持 signal,现在更推荐直接传 AbortSignal.timeout(3000),超时后请求会被真正中断。
any 做多节点择优
同一份资源部署在几个 CDN 上,同时请求,用最先成功的那个。某个节点挂了、返回错误都不要紧,只要还有一个能用,用户就感知不到。这时如果用 race,一旦最快返回的恰好是一个错误,整个请求就失败了,兜底完全没起作用。
回答前,多想一步

容易答错的地方

以为 race 会自动取第一个成功的
race 对成功和失败一视同仁。很多人用它做多源择优,结果某个节点秒回一个 500,整个请求就失败了。要跳过失败,必须用 any。
以为结果定了,其他请求就被取消了
race 和 any 只是不再关心剩下的结果,剩下的 Promise 该执行还执行,请求照样发完。要真正停掉,得给每个请求传 signal,拿到结果后调用 controller.abort()。
忽略空数组的差别
Promise.race([]) 永远 pending,因为没有任何一个能结束。Promise.any([]) 立刻以 AggregateError 拒绝,因为不可能有成功。列表是动态拼出来的时候,这两种表现都可能让页面卡住或者报出奇怪的错。
试着用自己的话回答

面试官还会怎么问?

any 全部失败时,怎么拿到每个失败原因?

它拒绝的是一个 AggregateError,每个失败原因按输入顺序放在 err.errors 数组里。遍历这个数组就能知道每个节点分别是什么原因失败的。

手写一个 Promise.race 怎么写?

返回一个 new Promise,遍历输入,对每一项调用 Promise.resolve(item).then(resolve, reject)。谁先调用 resolve 或 reject 谁就生效,后面的调用会被忽略,因为 Promise 的状态只能改变一次。用 Promise.resolve 包一下是为了兼容数组里的普通值。

四个组合方法怎么一起记?

按「等不等全部」和「失败算不算」来分。Promise.all 等全部成功,有一个失败就失败。Promise.allSettled 等全部结束,永远不失败。Promise.race 取第一个结束的。Promise.any 取第一个成功的,全部失败才失败。all 和 any 正好是一对反义:一个是有一个失败就失败,一个是有一个成功就成功。

从一道题,走向一组知识

把知识连起来

异步与 Promise

在 new Promise 的 executor 里直接 throw,Promise 会变成 rejected 吗?

race 常用来包一个会超时拒绝的 Promise,executor 里 reject 和 throw 的区别在这里会直接用到。

异步与 Promise

then 回调里返回一个 Promise,下一个 then 拿到的是 Promise 还是值?

race 和 any 拿到的值如果本身是 Promise,也会被自动展开,原理和 Promise 嵌套展开一样。

参考资料

  • JavaScript:异步与 Promise参考资料

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 同一组任务,两种结果
  3. 各自最适合的场景
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑