我正在尝试使用重试来实现Angular5 http.get。我写了
http.get<any>('/api/study').retryWhen(
(errors: Observable<any>):Observable<any> => {
return errors.flatMap((error: any) => {
if (error.status == 500) {
return Observable.of(error.status).delay(1000);
}
return Observable.throw(error);
}).take(5);
});
如果它出现错误500,这将继续重试最多5次。但是,如果它连续出现5次失败,那么返回成功(使用空数据)。我不希望这样。相反,我希望它抛出最后一个错误。
我尝试将.concat(Observable.throw({}))
放在take()之后,这样可行,但它没有给我任何信息,例如最近错误的状态代码。
如何在上次重试失败后获取最新错误?
答案 0 :(得分:3)
您无需使用take(5)
来计算失败的尝试次数,并使用局部变量自行计算。
例如,你可以这样做:
http.get<any>('/api/study').retryWhen((errors: Observable<any>) => {
let errors = 0;
return errors.flatMap((error: any) => {
if (errors++ < 5 && error.status == 500) {
return Observable.of(error.status).delay(1000);
}
return Observable.throw(error);
});
});
答案 1 :(得分:1)
.retryWhen
只能完成或错误 - 在这两种情况下,都会中止进一步的重试。 See docs
所以当你添加.take(5)
时,你基本上是在告诉它重试5次而然后完成,此时它只能完成(因此也不能返回错误 - 它是一个或另一个,而不是两者。)
因此使用.take()
无法解决您的问题。
不幸的是,这意味着您必须在重试时自己跟踪重试次数 - 所以对于5个计数,您只需让它返回错误(这将触发重试),最后在计数6上您手动抛出错误。然后,您可以在catch块中捕获最终错误。
这样的事情(代码没有经过测试,但显示了这个想法):
http.get<any>('/api/study').retryWhen(err => {
console.log('retrying');
let retries = 0;
return err
.delay(1000)
.map(error => {
if (retries++ === 6) {
console.log('retry number ', retries);
throw error; <- THIS WILL CAUSE retryWhen to complete
}
return error;
});
})
.catch(err => {
console.log('caught');
return Observable.of(err);
})
.subscribe(data => {
console.log('subscriber');
console.log(data);
});
作为旁注,添加.concat(Observable.throw({}))并不能解决您的问题,因为当它触发时,您的5次重试已完成,因此重试时已完成(即返回完成) ,所以没有错误)。这就是concat无法抛出最后一个错误的原因,因为它从未收到它。