angular - 如何使用 rxjs 重试并在此之后执行函数
问题描述
我想重试一个 api 调用 10 次(等待一秒钟,因为它失败直到下一次执行),如果这 10 次失败,那么我将执行一个函数,这是我的方法:
private handleError(error, req: HttpRequest<any>, next: HttpHandler): Observable<any> {
if (error.status === 0) {
return next.handle(req).pipe(
catchError(err => timer(1000).pipe(switchMapTo(this.checkConnection(err)))),
retry(10)
);
}
}
private checkConnection(error): Observable<any> {
console.log(error)
return EMPTY;
}
这不起作用,通过使用提供的有关在重试和捕获错误之间切换顺序的解决方案,计时器停止工作。
我也尝试过 retryWhen:
if (error.status === 0) {
return next.handle(req).pipe(
retryWhen(errors => errors.pipe(delay(1000), take(10),
concatMapTo(this.checkConnection(errors)))));
}
然后我的问题只重试一次,我的“checkConnection”函数中没有原始错误
通过使用控制台日志,我可以看到这是任何尝试都会执行的,而我想要得到的是执行 10 次后执行。
我不知道怎么做。
我正在使用角度 8。
根据提供的答案,我的代码应该可以工作,但它没有,它有一个编译错误,这是我的全部服务:
import { throwError, Observable , EMPTY } from 'rxjs';
import { Injectable } from '@angular/core';
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { catchError, delay, retryWhen, take, concatMap } from 'rxjs/operators';
import { Router } from '@angular/router';
@Injectable()
export class HttpErrorInterceptorService implements HttpInterceptor {
private handleError(error, req: HttpRequest<any>, next: HttpHandler): Observable<any> {
if (error.status === 401) {
this.router.navigate(['/login']);
return EMPTY; // Stops processing
} else if (error.status === 403) {
this.router.navigate(['/unauthorized']);
return EMPTY; // Stops processing
} else if (error.status === 0) {
return next.handle(req).pipe(
retryWhen((errors) => {
return errors.pipe(
delay(1000),
take(10), // Number of retries
concatMap(throwError)// Let the error bubble up again
);
}),
catchError((err) => this.checkConnection(err)));
}
return throwError(error);
}
private checkConnection(error): Observable<any> {
//it will have more logic in future, this is just the starting point to this function
console.log(error)
return EMPTY;
}
constructor(private router: Router) {
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).pipe(
catchError((error) => this.handleError(error, req, next))
);
}
}
编译错误是
'(error: any, scheduler?: SchedulerLike) => Observable' 类型的参数不可分配给'(value: any, index: number) => Observable' 类型的参数。参数 'scheduler' 和 'index' 的类型不兼容。类型“编号”不可分配给类型“SchedulerLike”。
解决方案
retry
应该准确地捕捉到内部错误 N 次。第 N+1 次它会按预期传递。当前,您捕获每个错误并将其通过管道传输到checkConnection
. 基本上切换retry
并且catchError
在您的原始示例中应该已经完成了这项工作。
import {Observable, throwError, EMPTY} from 'rxjs';
import {concatMap, delay, retryWhen, take} from 'rxjs/operators';
private handleError(error, req: HttpRequest<any>, next: HttpHandler): Observable<any> {
if (error.status === 0) {
return next.handle(req).pipe(
retryWhen((errors) => {
return errors.pipe(
delay(1000),
take(10), // Number of retries
concatMap(throwError), // Let the error bubble up again
)
),
catchError((err) => this.checkConnection(err))),
);
}
}
private checkConnection(error): Observable<any> {
console.log(error)
return EMPTY;
}
推荐阅读
- firebase - 使用 Admin SDK 删除时如何将项目计数器保留在集合中
- python - 如何执行存储为具有特定参数的字典值的函数?
- rust - 如何在泛型中指定迭代器类型?
- java - 如何从 jar 文件运行 Maven Failsafe 集成测试?
- servicenow - 是否可以在 Servicenow 中配置多个选项列表?
- autodesk-forge - 针对 beta 服务器创建场景定义时出现 422 错误
- puppeteer - 如何在 Puppeteer 中拦截服务器发送的事件消息
- android - createConfigurationContext 无法在 API 级别 <26 上以编程方式更改语言
- reactjs - 调用渲染后 React setstate 在 IE11 中不起作用
- vba - 多个附件名称相同时如何自动打印发票?