我有一个向 API 发出请求的函数。有时 API 会出现一些小问题,时不时有一两秒钟不可用,导致我想再次调用该函数的错误。由于此回调之后还有另外 70~80 行代码,我不想用 if(error) <do the same stuff> else <as here>
拆分流程
尝试了一段时间后,我最终使用了一个 do-while(error) 循环,它可以工作但会阻塞。有这样做的异步方式吗?
我的代码(为概括而简化):
//This is the request part
function bar(j, callback){
j++;
//simulated error
if(j<=10){
return( callback('dont', j) );
}
//simulated success
else{
return( callback(null, j) );
}
}
//This is the main function - part of a bigger piece in my code
function foo(){
var i = 0;
var err = 'yes'; //else we'd get an 'err is not defined'
do{
bar(i, function(error, j){
i = j
err = error;
if(error){
console.log(i);
}
else{
return( console.log('done it!') );
// There's more here in my code
}
});
} while (err);
console.log('I blocked');
}
foo();
编辑:
对于那些感兴趣的人,这是输出:
1
2
3
4
5
6
7
8
9
10
done it!
I blocked
最佳答案
我建议您为您的操作创建一个函数。如果失败,您可以设置一个较短的计时器并在该计时器触发后重试。这将为您提供重试之间的异步行为,并且服务器中的其他代码可以运行。
function requestRetry(url, data, retryTimes, retryDelay, callback) {
var cntr = 0;
function run() {
// try your async operation
request(..., function(err, data) {
++cntr;
if (err) {
if (cntr >= retryTimes) {
// if it fails too many times, just send the error out
callback(err);
} else {
// try again after a delay
setTimeout(run, retryDelay);
}
} else {
// success, send the data out
callback(null, data);
}
});
}
// start our first request
run();
}
requestRetry(someUrl, someData, 10, 500, function(err, data) {
if (err) {
// still failed after 10 retries
} else {
// got successful result here
}
});
这是一个相当简单的重试方案,它只是在固定的时间间隔内重试固定的次数。更复杂的方案实现了一种回退算法,它们从相当快的重试开始,但在前几次失败后回退到重试之间的较长时间段,以便为服务器提供更好的恢复机会。如果碰巧有很多客户端都在快速重试,那么一旦你的服务器出现问题,你就会遇到雪崩式故障,因为所有客户端突然开始快速重试,这只会让你的服务在尝试时遇到更多麻烦处理所有这些请求。退避算法旨在使服务器更有可能防止雪崩故障并使其更容易恢复。
如果您正在等待服务在中断一段时间后重新上线,则退避方案也更合适。
关于node.js - Nodejs - 错误回调的重新调用函数 - 是否有非阻塞方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35195725/