我正在通过ErrorInterceptor
实现自动开发重试功能HttpInterceptor
。我读到这retryWhen
正是我所需要的。我希望它发生的是有条件地重试点击 Snackbar 的“重试”按钮,我不希望它触发无限的请求(所以,也许 3 次后你不能再试一次)。问题是现在我不知道如何在单击通知小吃栏上的操作按钮后有条件地重试
我已经尝试触发 notificationService ,它使用简单的代码显示通知:
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request).pipe(
retryWhen(error => {
this.notificationService.showNotification('problem RETRY', NotificationActionLabel.Retry, 4000, () => {
console.log('retrying');
return of(error);
});
return throwError(error);
}),
这不再重试该功能,它只是停止。
然后我找到了一些关于 retryWhen 的代码,它描述了一个 generalRetryStrategy https://www.learnrxjs.io/operators/error_handling/retrywhen.html。我添加了这个,但我希望它有条件地触发(链接到操作按钮)。
我在通知服务上有一个回调函数
export class NotificationService {
constructor(private snackBar: MatSnackBar) {}
public showNotification(message: string, action?: string, duration?: number, callBackFunction?: Function) {
const defaultDuration: number = 2500;
const notificationRef = this.snackBar.open(message, action, {
duration: duration == null ? defaultDuration : duration,
panelClass: ['snackbar-styling'],
});
notificationRef.onAction().subscribe(result => callBackFunction(result));
}
}
拦截器现在如下:
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request).pipe(
retryWhen(this.genericRetryStrategy()),
catchError((error: HttpErrorResponse) => {
let errorMessage = '';
// Client side error
if (error.error instanceof ErrorEvent) {
errorMessage = `Error: ${error.error.message}`;
} else {
// Server Side Error
errorMessage = this.generateErrorMessage(error);
}
this.loggingService.logErrorMessage(error.error.message);
this.notificationService.showNotification(errorMessage, null, 4000);
return throwError(error.error.message);
}),
);
使用以下函数 genericRetryStrategy,请注意这与 learn-rxjs 中的代码几乎没有什么不同。
genericRetryStrategy = ({
maxRetryAttempts = 3,
scalingDuration = 1000,
excludedStatusCodes = [],
}: {
maxRetryAttempts?: number;
scalingDuration?: number;
excludedStatusCodes?: HttpStatusCode[];
} = {}) => (attempts: Observable<any>) => {
return attempts.pipe(
mergeMap((error, i) => {
this.notificationService.showNotification('attempting', 'retry', 4000, () => {
const retryAttempt = i++;
// if maximum number of retries have been met
// or response is a status code we don't wish the retry, throw error
if (retryAttempt > maxRetryAttempts || excludedStatusCodes.find(e => e === error.status)) {
return throwError(error);
}
console.log(`Attempt ${retryAttempt}: retrying in ${retryAttempt * scalingDuration}ms`);
//retry after 1s, 2s, etc...
return timer(retryAttempt * scalingDuration);
});
return throwError(error);
}),
finalize(() => console.log('We are done!')),
);
};
我希望它仅在真正调用通知服务回调函数时才触发重试功能(因此单击“重试”按钮)。现在它立即跳过通知服务调用并返回错误(throwError(error))
。
任何帮助深表感谢。