Promise.withResolvers()

基线 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() 构造函数相同的签名——接受一个可以调用 resolvereject 回调作为参数的 executor 函数。

示例

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

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

规范

规范
ES Promise.withResolvers (2023)
# sec-promise.withResolvers

浏览器兼容性

BCD 表仅在启用 JavaScript 的浏览器中加载。

另请参阅