Promise出了个新方法:Promise.withResolvers()
有时候我们需要把 Promise 的 resolve 或者 reject 这两个参数给取出来,比如:
let resolve, reject;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
Math.random() > 0.5 ? resolve("ok") : reject("not ok");这样挺麻烦的,总是定义额外变量去存储这个 resolve,reject。但在 Chrome 119(发布于2023年10月31日)版本之后,可以使用以下方式实现:
const { promise, resolve, reject } = Promise.withResolvers();
Math.random() > 0.5 ? resolve("ok") : reject("not ok");是不是更简洁,可以看出Promise.withResolvers()的主要作用是把 Promise实例、resolve、reject 解构出来供我们使用。它是一个静态方法,返回一个包含新的 Promise 对象和两个函数的对象,用于解决或拒绝该 Promise。这两个函数对应于传递给 Promise() 构造函数的执行器的两个参数。
Promise.withResolvers 的关键区别在于现在解决和拒绝函数与 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 的示例中,将 Node.js 的可读流转换为异步可迭代对象。每个 promise 代表一批可用的数据,每次读取当前批次时,将创建一个新的 promise 用于下一个批次。请注意,事件监听器只添加了一次,但实际上每次都会调用不同版本的解决和拒绝函数。
此外,Promise.withResolvers 也适用于非 Promise 构造函数。可以在任何实现了与 Promise() 构造函数相同签名的构造函数上调用它。例如,我们可以在一个将 console.log 作为解决和拒绝函数传递给执行器的构造函数上调用它。
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 解决总而言之,Promise.withResolvers 提供了一种更简洁、更高级的方式来处理 Promise 的解决和拒绝,并且支持更多灵活的用例,使代码更易于阅读和维护。
Promise.withResolvers这个新api,目前处于Stage-3阶段,需要谷歌 117 以上的版本才能使用这个方法,Stage-3就是候选的意思,这些方法的提案分为几个阶段
Stage 0 - Strawman (草案阶段): 这是提案的初始阶段,通常是一些初步的想法或建议。这些提案还没有得到正式的讨论和接受。 Stage 1 - Proposal (提案阶段): 在这个阶段,提案已经经过了初步的讨论,并且有了详细的说明。它们通常由一个或多个TC39委员会成员提交,并等待进一步的审查和反馈。 Stage 2 - Draft (草案阶段): 在这个阶段,提案已经经过了初步的审查,包括语法和语义方面的考虑。提案可能会在这个阶段进行一些修改和改进。 Stage 3 - Candidate (候选阶段): 当提案达到这个阶段时,它们被认为是成熟的,可以被实施到JavaScript引擎中。这通常包括详细的规范文档和实际的参考实现。 Stage 4 - Finished (完成阶段): 这是提案的最终阶段,表示它们已经被正式接受为ECMAScript标准的一部分,可以在各种JavaScript环境中广泛使用。
期待不久的将来,这个方法能到Stage 4阶段,并在项目中广泛使用!
本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!