Я разрабатываю функцию повтора автоматически, ErrorInterceptor
реализуя HttpInterceptor
.Я прочитал, что retryWhen
это именно то, что мне нужно.То, что я хочу, чтобы это произошло, - это условная повторная попытка по нажатию на кнопку Snackbar 'RETRY', и я не хочу, чтобы она запускала неограниченные запросы (поэтому, возможно, после 3 раз вы не сможете повторить попытку).Проблема в том, что теперь я не знаю, как условно повторить попытку после нажатия кнопки действия на панели уведомлений
Я уже пытался просто запустить службу уведомлений, которая отображает уведомление с простым кодом:
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))
.
Любая помощь очень ценится.