Promise.withResolvers()

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

¥The Promise.withResolvers() static method returns an object containing a new Promise object and two functions to resolve or reject it, corresponding to the two parameters passed to the executor of the Promise() constructor.

语法

¥Syntax

js
Promise.withResolvers()

参数

¥Parameters

没有任何。

¥None.

返回值

¥Return value

包含以下属性的普通对象:

¥A plain object containing the following properties:

promise

一个 Promise 对象。

resolve

解决承诺的函数。有关其语义,请参阅 Promise() 构造函数参考。

reject

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

描述

¥Description

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

¥Promise.withResolvers() is exactly equivalent to the following code:

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

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

¥Except that it is more concise and does not require the use of let.

使用 Promise.withResolvers() 时的主要区别在于,解决函数和拒绝函数现在与 Promise 本身位于同一范围内,而不是在执行程序中创建和使用一次。这可能会启用一些更高级的用例,例如将它们重用于重复事件时,特别是对于流和队列。与在执行器中封装大量逻辑相比,这通常也会导致更少的嵌套。

¥The key difference when using Promise.withResolvers() is that the resolution and rejection functions now live in the same scope as the promise itself, instead of being created and used once within the executor. This may enable some more advanced use cases, such as when reusing them for recurring events, particularly with streams and queues. This also generally results in less nesting than wrapping a lot of logic within the executor.

Promise.withResolvers() 是通用的并且支持子类化,这意味着它可以在 Promise 的子类上调用,并且结果将包含子类类型的承诺。为此,子类的构造函数必须实现与 Promise() 构造函数相同的签名 - 接受可以使用 resolvereject 回调作为参数进行调用的单个 executor 函数。

¥Promise.withResolvers() is generic and supports subclassing, which means it can be called on subclasses of Promise, and the result will contain a promise of the subclass type. To do so, the subclass's constructor must implement the same signature as the Promise() constructor — accepting a single executor function that can be called with the resolve and reject callbacks as parameters.

示例

¥Examples

将流转换为异步可迭代

¥Transforming a stream to an async iterable

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

¥The use case of Promise.withResolvers() is when you have a promise that should be resolved or rejected by some event listener that cannot be wrapped inside the promise executor. The following example transforms a Node.js readable stream to an async iterable. Each promise here represents a single batch of data available, and each time the current batch is read, a new promise is created for the next batch. Note how the event listeners are only attached once, but actually call a different version of the resolve and reject functions each time.

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()

¥Calling withResolvers() on a non-Promise constructor

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

¥Promise.withResolvers() is a generic method. It can be called on any constructor that implements the same signature as the Promise() constructor. For example, we can call it on a constructor that passes console.log as the resolve and reject functions to 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

规范

Specification
ES Promise.withResolvers (2023)
# sec-promise.withResolvers

¥Specifications

浏览器兼容性

BCD tables only load in the browser

¥Browser compatibility

也可以看看