在Angular 2+;中订阅后API调用失败时如何重试;
我正在调用API以获取随机详细信息。问题是,有时我得到502错误作为坏网关,它也可能由于坏的网络连接而中断。 下面是我的API调用代码在Angular 2+;中订阅后API调用失败时如何重试;,angular,rxjs,interceptor,angular-httpclient,retrywhen,Angular,Rxjs,Interceptor,Angular Httpclient,Retrywhen,我正在调用API以获取随机详细信息。问题是,有时我得到502错误作为坏网关,它也可能由于坏的网络连接而中断。 下面是我的API调用代码 // COMPONENT API CALL SUBSCRIBE this._service.post('randomAPI/getdetails', filters).subscribe((response: any) => { this.itemList = response; }); // SHARED SERVIC
// COMPONENT API CALL SUBSCRIBE
this._service.post('randomAPI/getdetails', filters).subscribe((response: any) => {
this.itemList = response;
});
// SHARED SERVICE
post<T>(url: string, body: any): Observable<T> {
return this.httpClient.post<T>(url, body);
}
//组件API调用订阅
此._service.post('randomAPI/getdetails',filters.).subscribe((响应:any)=>{
this.itemList=响应;
});
//共享服务
post(url:string,body:any):可观察{
返回此.httpClient.post(url,正文);
}
每当我收到500或502服务器错误时,使用拦截器我将路由到一个错误页面,以通知用户服务器问题
相反,如果API失败,我可以让它在组件级或拦截器级再试一次,然后路由到错误页面吗
// INTERCEPTOR
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request).pipe(catchError(error => {
if (error.status === 401 || error.status === 400 || error.status === 403) {
this.router.navigateByUrl('abort-access', { replaceUrl: true });
} else if (error.status === 500 || error.status === 502) {
this.router.navigateByUrl('server-error', { replaceUrl: true });
}
return throwError("error occured");
}));
}
//拦截器
拦截(请求:HttpRequest,下一步:HttpHandler):可观察{
返回next.handle(request).pipe(catchError)(error=>{
如果(error.status==401 | | error.status==400 | | | error.status==403){
this.router.navigateByUrl('abort-access',{replaceUrl:true});
}else if(error.status==500 | | error.status==502){
this.router.navigateByUrl('server-error',{replaceUrl:true});
}
返回投掷器(“发生错误”);
}));
}
我看到了一些示例,因为它们使用管道并添加retryWhen()来实现这一点。但是,由于我是一个非常新的角度,我不能想出一个方法来做到这一点
有人能帮忙吗?您可以使用
retryWhen
操作员。这背后的原理是当您不想重试时抛出错误
retryWhen
实际上是一种奇特的catchError
,除非抛出错误,否则它将自动重试
拦截(请求:HttpRequest
限制重试次数
这样做的危险在于,您将执行连续的请求,直到服务器不返回500或502。在现实世界的应用程序中,您可能希望限制重试次数,并且可能会在其中设置某种延迟,以避免请求淹没服务器
为此,您可以使用take(n)
将请求限制为n
失败的尝试。这对您不起作用,因为take
将阻止可观察对象进入catchError
,并且您将无法执行导航
相反,您可以设置重试限制,并在达到重试限制后抛出错误
const retryLimit=3;
设尝试=0;
拦截(请求:HttpRequest)执行此功能
delayedRetry(delayMs:number,maxRetry:number){
let retries=maxRetry;
return (src:Observable<any>)=>
src.pipe(
retryWhen((errors:Observable<any>)=>errors.pipe(
delay(delayMs),
mergeMap(error =>retries -- > 0 ?
of(error):throwError("Retrying..."))
))
)
}
delayedRetry(delayMs:number,maxRetry:number){
让retries=maxRetry;
回报率(src:可观察)=>
钢骨混凝土管(
retryWhen((错误:可观察)=>errors.pipe(
延迟(延迟毫秒),
合并映射(错误=>重试-->0?
of(错误):投掷者(“重试…”)
))
)
}
在api url中调用此函数
return this.http.get<RouteData[]>(url).pipe(
this.delayedRetry(10000,4),
catchError(err => {
console.error(err);
return EMPTY;
}),
shareReplay()
);
返回这个.http.get(url.pipe)(
这是延迟测光法(10000,4),
catchError(err=>{
控制台错误(err);
返回空;
}),
shareReplay()
);
您希望在什么条件下重试?只有当失败时,准确地说,主要是500和502错误状态时,当我们从组件调用API时,我们才能在订阅方法中使用retryWhen?否。在订阅之前在管道中发生时重试。您可以将管道添加到任何可观察的对象。可观察的.pipe(map()).pipe(map()).pipe(retryWhen()).subscribe()
。因此,您的组件将执行类似于的操作。service.makeRequest().pipe(retryWhen()).subscribe()
我有一个疑问-如果我编写这个.service.makeRequest().pipe(retryWhen()).subscribe((resp)=>{this.list=resp});,您的意思是说。在重试完成之前,不会为列表分配resp?是的。retryWhen
会因为收到错误而发出另一个请求,因此无论如何都不会有列表可供使用。