Promise.withResolvers() 静态方法返回一个对象,其包含一个新的 Promise 对象和两个函数,用于解决或拒绝它,对应于传入给 Promise() 构造函数执行器的两个参数。
Promise.withResolvers() 完全等同于以下代码:
let resolve, reject;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
使用 Promise.withResolvers() 关键的区别在于解决和拒绝函数现在与 Promise 本身处于同一作用域,而不是在执行器中被创建和一次性使用。
示例:
将流转换为异步可迭代对象
当你有一个 promise,需要通过无法包装在 promise 执行器内的某个事件监听器来解决或拒绝。
以下示例将 Node.js 的可读流转换为异步可迭代对象。这里的每个 promise 代表一个可用的数据批次,每次读取当前批次时,就会为下一个批次创建一个新的 promise。
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() 构造函数相同签名的构造函数上调用。例如,我们可以在一个将 console.log 作为 resolve 和 reject 函数传入给 executor 的构造函数上调用它:
class NotPromise {
constructor(executor) {
// “resolve”和“reject”函数和原生的 promise 的行为完全不同
// 但 Promise.withResolvers() 只是返回它们,就像是原生的 promise 一样
executor(
(value) => console.log("以", value, "解决"),
(reason) => console.log("以", reason, "拒绝"),
);
}
}
const { promise, resolve, reject } = Promise.withResolvers.call(NotPromise);
resolve("hello");
// 输出:以 hello 解决
目前浏览器的兼容性如下所示: