如果发生内部服务器错误,我会使用 backoff 方法的概念来重试请求。我的意思是不是 401
, 403
或类似的。我的目标是在服务器没有响应和/或发送响应时间过长时重试请求,例如在 pending
状态的情况下。我确实为此定义了超时限制(在服务中)。
我的问题是,所有案例/错误都会调用 retryWhen
功能,包括 401
。
我相信我可能需要重构我的功能/代码才能使其正常工作。我正在努力解决这个问题,但却无法按预期工作。
retryWhen
函数返回一个可观察的流,指示何时重试,因此它无法在我的代码中工作。
public userLogin(userName, userPass: string) {
this.theService.login(userName, userPass)
.retryWhen(attempts => Observable.range(1, 3)
.zip(attempts, i => i)
.mergeMap(i => {
console.log("delay retry by " + i + " second(s)");
// Show a message to user to wait
if ( i === 3 ) {
// Show Server doesn't respond... try later
}
return Observable.timer(i * 3000);
})
).subscribe(
res => {
// handle and show response result
},
err => {
console.log(err);
if ( err === 401 ) {
// handle 401 error
} else {
// handle other error
}
}
);
}
以下question也是一种处理相同问题的方法,我尝试使用有关mergeMap(error => {...})
的提示,但它对我没有用。
如果内部服务器出现错误或某种情况,请问我应该如何重构我的代码以重试请求?我提到没有 401
, 403
或类似内容。
答案 0 :(得分:3)
您可以按如下方式重新列出retryWhen
运算符中列入黑名单的错误:
/**
* Performs a retry on an exponential backoff with an upper bounds.
* Will rethrow the error if it is in the blacklist or the retry
* attempts have exceeded the maximum.
* @param {number} initialDelay
* @param {number} maxRetry - maximum number of times to retry
* @param {number[]} errorWhiteList - whitelist of errors to retry on (non-transient)
*/
function expontentialRetry(
initialDelay,
maxRetry,
errorWhiteList
) {
return (errors) => errors.scan((retryAttempts, error) => {
if(!errorWhiteList.includes(error.status) || retryAttempts > maxRetry) {
throw error;
}
return retryAttempts + 1;
}, 0).switchMap((retryAttempts) => {
// calculate exponential backoff
let delay = Math.pow(2, retryAttempts - 1) * initialDelay;
console.log(`Retry attempt #${retryAttempts} in ${delay}ms`);
return Rx.Observable.timer(delay);
});
}
let count = 0;
const fakeApiCall = Rx.Observable.create((o) => {
if (count < 5) {
o.error({ status: 504 });
} else {
o.error({ status: 500 });
}
count++;
});
fakeApiCall.retryWhen(expontentialRetry(100, 10, [504]))
.subscribe(
(x) => { console.log('next', x); },
(error) => { console.log('error', error); },
() => { console.log('complete'); }
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.10/Rx.min.js"></script>