我想实现一种逻辑,如果对当前起点的调用失败,则重试对另一个起点的API调用。 我希望在服务层中处理它,因为不要在每个组件中实现此逻辑。
例如,我在端点服务中具有此类功能
getAll(): Observable<IssueListItem[]> {
let endpointUrl = `${this.apiConnectionService.getApiUrl()}api/Issues`;
return this.http.get<IssueListItem[]>(endpointUrl, { headers: this.dataService.requestHeaders })
.pipe(retryOtherApi(this.apiConnectionService),
catchError(error => this.handleError(error)));
}
此函数的使用者如下:
ngOnInit() {
this.issuesEndpointService.getAll()
.subscribe(_ => this.issues = _);
}
我希望它对重试逻辑一无所知。
因此,我尝试创建一个运算符'retryOtherApi',将原点切换到另一个原点。
export function retryOtherApi(apiConnectionService: ApiConnectionService) {
const maxRetry = apiConnectionService.apiOriginsCount;
return (src: Observable<any>) => src.pipe(
retryWhen(_ => {
return interval().pipe(
flatMap(count => {
console.log('switch to: ' + apiConnectionService.getApiUrl())
apiConnectionService.switchToOther();
return count === maxRetry ? throwError("Giving up") : of(count);
})
);
})
);
}
切换有效,但不幸的是,没有调用整个getAll函数,并且使用相同的旧URL重试了n次。
所以问题是,如果当前API不可用,如何对其他API逻辑实施通用重试。
如果将问题改述为更常见的情况,就好像在当前参数失败时如何用其他参数调用HTTP端点。
答案 0 :(得分:0)
public getAll(): Observable<IssueListItem[]> {
let call = () => {
let endpointUrl = `${this.apiConnectionService.getApiUrl()}api/Issues`;
return this.http.get<IssueListItem[]>(endpointUrl, { headers: this.dataService.requestHeaders })
};
return <Observable<IssueListItem[]>>call()
.pipe(
retryOtherApi(this.apiConnectionService, () => call()),
catchError(error => this.handleError(error))
);
}
这是重试运算符:
export function retryOtherApi(apiConnectionService: ApiConnectionService, recall: () => Observable<any>) {
const maxRetry = apiConnectionService.apiOriginsCount;
let count = 0;
let retryLogic = (src: Observable<any>) => src.pipe(
catchError(e => {
if (e.status === 0) {
apiConnectionService.switchToOther();
console.log('switch to: ' + apiConnectionService.getApiUrl())
return count++ === maxRetry ? throwError(e) : retryLogic(recall());
} else {
return throwError(e);
}
}));
return retryLogic;
}
它有效,但是: