For AI agents: the complete documentation index is available at /tc39-atlas/llms.txt, the full documentation bundle is available at /tc39-atlas/llms-full.txt, and this page is available as Markdown at /tc39-atlas/proposals/year/2021/proposal-promise-any.md.
  • 简体中文
  • Promise.any S4

    提案概览
    提案速览

    该提案引入了 Promise.any,它从可迭代对象中取第一个兑现的 promise 进行兑现,如果全部拒绝则用 AggregateError 拒绝。它还添加了 AggregateError 类。

    Note

    以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。

    ECMAScript 提案:Promise.any + AggregateError

    作者:Mathias Bynens, Kevin Gibbons, Sergey Rubanov

    ** Champion **:Mathias Bynens

    阶段TC39 流程中的第 4 阶段。

    动机

    Promise 领域中有四个主要的组合器

    名称描述
    Promise.allSettled不短路在 ES2020 中添加 ✅
    Promise.all当输入值被拒绝时短路在 ES2015 中添加 ✅
    Promise.race当输入值被确定(settled)时短路在 ES2015 中添加 ✅
    Promise.any当输入值被兑现(fulfilled)时短路本提案 🆕 预定于 ES2021

    这些组合器在用户态的 promise 库中都很常见,且各自独立有用,分别服务于不同的用例。

    提议的解决方案

    Promise.any 接受一个 promise 的可迭代对象,并返回一个 promise,该 promise 由第一个被兑现的给定 promise 兑现,或者如果所有给定的 promise 都被拒绝,则用一个包含拒绝原因的 AggregateError 拒绝。(如果发生更根本的错误,例如迭代可迭代对象时抛出异常,Promise.any 会返回一个带有该异常的被拒绝的 promise。)

    高级 API

    try {
      const first = await Promise.any(promises);
      // 任意一个 promise 被兑现。
    } catch (error) {
      // 所有 promise 都被拒绝。
    }

    或者,不使用 async/await

    Promise.any(promises).then(
      (first) => {
        // 任意一个 promise 被兑现。
      },
      (error) => {
        // 所有 promise 都被拒绝。
      }
    );

    在上述示例中,error 是一个 AggregateError,这是一个新的 Error 子类,用于将各个错误分组在一起。每个 AggregateError 实例都包含一个指向异常数组的指针。

    常见问题解答

    为什么选择 any 这个名称?

    它清晰地描述了其功能,并且在提供此功能的用户态库中已有 any 名称的先例:

    为什么抛出 AggregateError 而不是数组?

    ECMAScript 语言中的主流实践是只抛出异常类型。生态系统中的现有代码很可能依赖于这样一个事实:目前,内置方法和语法抛出的所有异常都是 instanceof Error。增加一个可能抛出普通数组的新语言特性会打破这一不变量,并可能导致 Web 兼容性问题。此外,通过使用 Error 实例(或子类),可以提供堆栈跟踪——如果不需要,可以很容易地丢弃,但如果需要,以后无法再获得。

    示例

    以下代码片段检查哪个端点响应最快,然后将其记录下来。

    Promise.any([
      fetch('https://v8.dev/').then(() => 'home'),
      fetch('https://v8.dev/blog').then(() => 'blog'),
      fetch('https://v8.dev/docs').then(() => 'docs')
    ]).then((first) => {
      // 任意一个 promise 被兑现。
      console.log(first);
      // → 'home'
    }).catch((error) => {
      // 所有 promise 都被拒绝。
      console.log(error);
    });

    TC39 会议记录

    规范

    实现