Javascript 如何在异步/等待函数捕获错误时重试?
一般来说,我对JS和编程相当陌生,在尝试在异步函数中实现try/catch时遇到了以下问题。它看起来像这样:Javascript 如何在异步/等待函数捕获错误时重试?,javascript,loops,async-await,try-catch,settimeout,Javascript,Loops,Async Await,Try Catch,Settimeout,一般来说,我对JS和编程相当陌生,在尝试在异步函数中实现try/catch时遇到了以下问题。它看起来像这样: (async function main() { try { await myFunc(); } catch (e) { console.log(e) } setTimeout(main, 2000); }) (); 如您所见,它通过setTimeout调用自身循环,使其无限大。。。除非它捕捉到错误。当然,我想尝试在e的
(async function main() {
try {
await myFunc();
} catch (e) {
console.log(e)
}
setTimeout(main, 2000);
}) ();
如您所见,它通过setTimeout调用自身循环,使其无限大。。。除非它捕捉到错误。当然,我想尝试在e的某些实例中重试myFunc,但不知道如何在不删除setTimeout的情况下进行重试(这里的2s延迟很重要)
我尝试使用标签:
let critErrCount;
(async function main() {
critErrCount = 0;
lbl:
try {
await myFunc();
} catch (e) {
if (e instanceof errType1) {
console.log(`errType1: ${e}`);
continue lbl;
} else if (e instanceof errType2) {
critErrCount += 1;
console.log(`errType2: ${e}`);
console.log(`critErrCount: ${critErrCount}`);
if (critErrCount == 5) {
console.log(`Too many critErrs, aborting...`)
process.exit;
}
continue lbl;
} else {
process.exit
}
}
setTimeout(main, 2000);
}) ();
毫无疑问,它不起作用,因为正如我所了解的,“continue”在其他语言中的行为与“goto”不同,只在适当的循环中起作用(forEach、while、for等)。由于catch块内的setTimeout也因nodejs的运行时细节(显示为“非法的continue语句”)而不起作用,所以我没有主意了 您可以使用一种重试机制,它可以让您重试异步函数调用所需的次数,我写了如何做到这一点,但这里是实现:
/**
*执行承诺并使用指数退避重试
*基于它可以执行的最大重试次数
*@param{Promise}Promise承诺执行
*每次重试时执行@param{function}onRetry回调
*@param{number}maxRetries尝试的最大重试次数
*@returns{Promise}传入的给定承诺的结果
*/
函数重试(promise、onRetry、maxRetries){
//注意,我们在这里声明了一个内部函数
//所以我们可以封装重试,而不公开
//这也是一个递归函数
异步函数retryWithBackoff(重试){
试一试{
//确保我们不等待第一次尝试
如果(重试次数>0){
//这就是魔法发生的地方。
//每次重试时,我们都会以指数方式增加等待时间。
//下面是“maxRetries”=4的查找方式
//(2**1)*100=200毫秒
//(2**2)*100=400毫秒
//(2**3)*100=800毫秒
常数timeToWait=2**重试次数*100;
log(`waiting for${timeToWait}ms...`);
等待等待(时间等待);
}
回报等待承诺();
}捕获(e){
//仅在未达到限制时重试
//否则,让调用方处理错误
如果(重试次数<最大重试次数){
onRetry();
返回retryWithBackoff(重试次数+1);
}否则{
console.warn('已达到最大重试次数。冒泡错误')
投掷e;
}
}
}
返回retryWithBackoff(0);
}
/**
*等待给定的毫秒
*@param{number}毫秒指定的等待时间
*@returns{Promise}在给定的时间过后履行了承诺
*/
函数waitFor(毫秒){
返回新承诺((解析)=>setTimeout(解析,毫秒));
}
下面是如何使用retry
helper:
/**伪造前3次尝试失败的API调用
*并决定进行第四次尝试。
*/
函数GenerateFailablePicall(){
设计数器=0;
返回函数(){
如果(计数器<3){
计数器++;
拒绝(新错误(“模拟错误”));
}否则{
返回承诺。解析({status:“ok”});
}
};
}
/***使用指数退避测试重试*/
异步函数测试(){
const apiCall=generatefailableapcall();
const result=等待重试(
总之,
() => {
log(“onRetry调用…”);
},
4.
);
日志(“结果:”,结果);
}
test();
让它无限大。。。除非它捕捉到错误。即使出现错误,递归的setTimeout
仍会工作,对吗?为什么不使用setInterval
?@一定是正确的性能。但这里有一个陷阱:经过一些测试,我确定如果main
函数捕捉到一次错误,它将在多次(次数总是不同)迭代后出于未知原因自动终止。如果没有发现错误,它将继续按预期工作,直到发现一个错误为止。我很确定给定的代码不会导致您所说的。您能否将一个实时片段编辑成显示超时最终失败的问题?我想它会一直持续下去work@fadeys.worksetInterval
不考虑函数执行时间,我的目标是在代码执行后等待2000
秒,因为一年前我发布了这个问题,我以类似于您在这里提出的方式从头重写了我的脚本,所以你的答案很合适。谢谢