我想让一些JavaScript代码接受3个参数:
- 返回Promise的函数。
- 最大尝试次数。
- 每次尝试之间的延迟。
最后我使用了一个for
循环。我不想使用递归函数:这样,即使有50次尝试,调用堆栈也不会增加50行。
下面是代码的typescript版本:
/**
* @async
* @function tryNTimes<T> Tries to resolve a {@link Promise<T>} N times, with a delay between each attempt.
* @param {Object} options Options for the attempts.
* @param {() => Promise<T>} options.toTry The {@link Promise<T>} to try to resolve.
* @param {number} [options.times=5] The maximum number of attempts (must be greater than 0).
* @param {number} [options.interval=1] The interval of time between each attempt in seconds.
* @returns {Promise<T>} The resolution of the {@link Promise<T>}.
*/
export async function tryNTimes<T>(
{
toTry,
times = 5,
interval = 1,
}:
{
toTry: () => Promise<T>,
times?: number,
interval?: number,
}
): Promise<T> {
if (times < 1) throw new Error(`Bad argument: 'times' must be greater than 0, but ${times} was received.`);
let attemptCount: number;
for (attemptCount = 1; attemptCount <= times; attemptCount++) {
let error: boolean = false;
const result = await toTry().catch((reason) => {
error = true;
return reason;
});
if (error) {
if (attemptCount < times) await delay(interval);
else return Promise.reject(result);
}
else return result;
}
}
上面使用的delay
函数是一个承诺的超时:
/**
* @function delay Delays the execution of an action.
* @param {number} time The time to wait in seconds.
* @returns {Promise<void>}
*/
export function delay(time: number): Promise<void> {
return new Promise<void>((resolve) => setTimeout(resolve, time * 1000));
}
为了澄清:上面的代码工作,我只是想知道这是否是一个“好”的方法,如果不是,我如何改进它。
有什么建议吗?先谢谢你的帮助。
5条答案
按热度按时间kiz8lqtg1#
我不想使用递归函数:这样,即使有50次尝试,调用堆栈也不会增加50行。
这不是个好借口调用堆栈不会因异步调用而溢出,当递归解决方案比迭代解决方案更直观时,您可能应该使用它。
最后我使用了一个
for
循环。这是一个“好”的方法吗?如果不是,我该如何改进它?for
循环很好。它从1
开始有点奇怪,但基于0的循环更习惯。然而,不好的是你奇怪的错误处理。这个布尔型
error
标志在代码中不应该有位置。Using.catch()
is fine,但是try
/catch
也可以工作,应该是首选。r7xajy2e2#
您可能想看看async-retry,它正是您所需要的。这个包允许你重试异步操作,你可以配置(除其他事项外)重试之间的超时(即使有增加的因素),最大重试次数,…
通过这种方式,您不必重新发明轮子,而是可以依赖于在社区中广泛使用的经过验证的包。
wmtdaxz33#
在Promise中使用递归函数不会对调用堆栈造成问题,因为Promise会立即返回,并且
then
或catch
函数将在异步事件后调用。一个简单的JavaScript函数应该是这样的:
nukf8bse4#
你考虑过RxJS吗?
它非常适合在异步工作流中实现这种逻辑。
下面是一个例子,说明如何在不破坏公共API的情况下做到这一点。从Promise转换为Observable并返回)。在实践中,你可能希望在任何给定的项目中使用RxJS或Promises,而不是混合使用它们。
可能不值得为这一个逻辑添加整个库,但如果您的项目涉及许多复杂的异步工作流,那么RxJS非常棒。
qmelpv7a5#
下面是一些可以工作的代码。
助手
然后向它传递一个函数,成功时返回
true
。使用示例
因为它返回一个promise,你可以
await
它或使用then/catch
来解决它。