Promise.withResolvers()

Baseline 2024
新推出

自 ⁨2024 年 3 月⁩ 起,此功能可在最新的设备和浏览器版本上运行。此功能可能不适用于较旧的设备或浏览器。

Promise.withResolvers() 静态方法返回一个对象,该对象包含一个新的 Promise 对象,以及两个用于解析或拒绝它的函数,这对应于传递给 Promise() 构造函数的执行器的两个参数。

语法

js
Promise.withResolvers()

参数

无。

返回值

一个包含以下属性的普通对象

promise

一个 Promise 对象。

resolve

一个解析该 Promise 的函数。有关其语义,请参阅 Promise() 构造函数参考。

reject

一个拒绝该 Promise 的函数。有关其语义,请参阅 Promise() 构造函数参考。

描述

Promise.withResolvers() 完全等同于以下代码

js
let resolve, reject;
const promise = new Promise((res, rej) => {
  resolve = res;
  reject = rej;
});

只是它更简洁,并且不需要使用 let

使用 Promise.withResolvers() 的主要区别在于,解析和拒绝函数现在与 Promise 本身存在于同一作用域中,而不是在执行器中创建并仅使用一次。这可能启用一些更高级的用例,例如在重复使用它们来处理周期性事件时,尤其是在流和队列中。这通常也比将大量逻辑包装在执行器内导致更少的嵌套。

Promise.withResolvers() 是通用的,并且支持子类化,这意味着它可以被调用在 Promise 的子类上,并且结果将包含子类类型的 Promise。要做到这一点,子类的构造函数必须实现与 Promise() 构造函数相同的签名——接受一个单独的 executor 函数,该函数可以与 resolvereject 回调函数作为参数一起调用。

示例

将流转换为异步可迭代对象

Promise.withResolvers() 的用例是当您有一个 Promise 需要由无法包装到 Promise 执行器内的事件监听器来解析或拒绝时。以下示例将 Node.js 的 可读流 转换为 异步可迭代对象。这里的每个 promise 代表一个可用数据的批次,每次读取当前批次时,都会为下一批数据创建一个新的 Promise。请注意,事件监听器仅被附加一次,但每次实际调用不同的 resolvereject 函数版本。

js
async function* readableToAsyncIterable(stream) {
  let { promise, resolve, reject } = Promise.withResolvers();
  stream.on("error", (error) => reject(error));
  stream.on("end", () => resolve());
  stream.on("readable", () => resolve());

  while (stream.readable) {
    await promise;
    let chunk;
    while ((chunk = stream.read())) {
      yield chunk;
    }
    ({ promise, resolve, reject } = Promise.withResolvers());
  }
}

在非 Promise 构造函数上调用 withResolvers()

Promise.withResolvers() 是一个通用方法。它可以被调用在实现与 Promise() 构造函数相同签名的任何构造函数上。例如,我们可以将其调用在一个构造函数上,该构造函数将 console.log 作为 resolvereject 函数传递给 executor

js
class NotPromise {
  constructor(executor) {
    // The "resolve" and "reject" functions behave nothing like the native
    // promise's, but Promise.withResolvers() just returns them, as is.
    executor(
      (value) => console.log("Resolved", value),
      (reason) => console.log("Rejected", reason),
    );
  }
}

const { promise, resolve, reject } = Promise.withResolvers.call(NotPromise);
resolve("hello");
// Logs: Resolved hello

规范

规范
ECMAScript® 2026 语言规范
# sec-promise.withResolvers

浏览器兼容性

另见