Reputation: 441
I have a simple interceptor that handles requests and catches any http error using RXJS catchError. The second argument received in catchError is the caught observable. I want to, in some cases, return this error and let it propagate up to the error handler in the subscribe function. The problem is that returning th caught error causes an infinite loop (as seen in the example: https://stackblitz.com/edit/angular-u4gakr)
The intercept function in the interceptor where the catchError is stuck in a loop when reciving an HTTP error, like 404:
return next.handle(request)
.pipe(
catchError((error, caught$) => {
console.log('Returning caught observable');
return caught$;
})
);
I have probably misunderstood something about the interceptor or RxJS catchError. Any suggestion?
Upvotes: 17
Views: 13519
Reputation: 7835
caught$
is your original observable. When I describe in English what you have programmed, then it is something like "do something and when it fails, then log it and do it again".
It is worth it to have a look into the documentation of rxjs, there is this behavior described.
a function that takes as arguments err, which is the error, and caught, which is the source observable, in case you'd like to "retry" that observable by returning it again.
Source: https://rxjs.dev/api/operators/catchError
So, it is up to you to decide what you want to do.
You can retry the call (perhaps with a delay) in case of a 503
(service is not available). Or you can build an error-object and return this instead.
return next.handle(request)
.pipe(
catchError((error, caught$) => {
// a retry-logic
if (error.status === 503) {
return timer(5_000).pipe(switchMap(() -> caught$));
}
// non-error-return
console.log(...);
return of({ result: { error: error; });
})
);
// other option: send a message to user
return next.handle(request)
.pipe(
catchError((error) => {
this.messageBoxService.showErrorMessage('there was a problem, while talking the server');
return throwError(error);
})
);
Upvotes: 6
Reputation: 441
Turns out I needed to use return throwError(error)
as returning the caught observable, or of(error) both failed to return it properly to the subscribe functions error handler.
The final code is then:
return next.handle(request)
.pipe(
catchError((error) => {
console.log('Returning caught observable');
return throwError(() => new Error('The Error'));
})
);
Upvotes: 14
Reputation: 1273
You can change the return to just be this and the subscribe will handle the error.
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<any> {
const requestCopy = request.clone();
return next.handle(request).pipe(catchError(error => {
if (error.status === 404) {
return throwError(error)
} else {
return of()
}
}))
}
https://stackblitz.com/edit/angular-zz3glp
Upvotes: 2