引言
在JavaScript编程中,Promise
是一种处理异步操作的常用机制。Promise
对象代表了一个尚未完成但预期将来会完成的操作的结果。在本文中,我们将探讨如何通过使用 ES2024 的 Promise.withResolvers
API 来优化我们的 Promise
实现。
现有实现的问题
首先,让我们看一个简单的示例,展示在没有使用 Promise.withResolvers
时,如何实现一个函数,该函数在传入的另一个函数执行完毕后2秒才返回结果:
js
const returnAfterTwoSeconds = (func, ...args) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
try {
resolve(func(...args));
} catch (e) {
reject(e);
}
}, 2000);
});
};
虽然上述代码能够正常工作,但它的嵌套层次较深,对于初次阅读的人来说可能不够直观。
改进实现
为了提高代码的可读性,我们可以对上述实现进行一些改进:
js
const returnAfterTwoSeconds = (func, ...args) => {
let outerResolve = null;
let outerReject = null;
const promise = new Promise((resolve, reject) => {
outerResolve = resolve;
outerReject = reject;
});
setTimeout(() => {
try {
outerResolve(func(...args));
} catch (e) {
outerReject(e);
}
}, 2000);
return promise;
};
在这个改进版本中,我们首先创建了一个 Promise
对象,并暂存了它的 resolve
和 reject
方法。然后在 setTimeout
中调用这些方法,最后返回 Promise
对象。这样,即使 setTimeout
中的回调执行完毕,返回的 Promise
对象也会根据回调的结果变为 resolved 或 rejected。
使用 Promise.withResolvers
现在,让我们看看如何使用 Promise.withResolvers
来进一步简化我们的代码:
js
const returnAfterTwoSeconds = (func, ...args) => {
const { promise, resolve, reject } = Promise.withResolvers();
setTimeout(() => {
try {
resolve(func(...args));
} catch (e) {
reject(e);
}
}, 2000);
return promise;
};
可以看到,这个方法并没有为我们的代码带来性能或者说实现方式上的优化,但是它使用起来很简单,也很好理解~ 有助于提高代码的可读性和简洁~
Promise.withResolvers
详解
根据 MDN 文档,Promise.withResolvers
的语法如下:
- 语法:
Promise.withResolvers()
- 参数:无
- 返回值:
自定义实现
最后,我们可以自定义一个函数来模拟 Promise.withResolvers
的行为:
js
function myWithResolvers() {
let resolve = null;
let reject = null;
const promise = new Promise((_resolve, _reject) => {
resolve = _resolve;
reject = _reject;
});
return { promise, resolve, reject };
}
可以看到,这个api在实现上其实也很简单,只是把我们平常获取promise中resolve和reject的步骤封装到一个方法中,但为我们节省了很多时间~