Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/459.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在异步/等待函数捕获错误时重试?_Javascript_Loops_Async Await_Try Catch_Settimeout - Fatal编程技术网

Javascript 如何在异步/等待函数捕获错误时重试?

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的

一般来说,我对JS和编程相当陌生,在尝试在异步函数中实现try/catch时遇到了以下问题。它看起来像这样:

(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.work
setInterval
不考虑函数执行时间,我的目标是在代码执行后等待
2000
秒,因为一年前我发布了这个问题,我以类似于您在这里提出的方式从头重写了我的脚本,所以你的答案很合适。谢谢