This is a relatively small and simple article, but I felt it is still worth posting because of the utility of the topic.
anirbmuk / angular-error-handler
Angular 12 application to demonstrate global error handling against a REST-based backend
Any front-end application is all about serving data from a store, using end-points (REST/GraphQL or whichever you can think of). And a big part of your application's success is the way you can handle errors. The more gracefully you handle error situations, the better your users' experience will be.
On that note, let's talk about an approach to handle all sorts of errors in an Angular application.
The idea behind this article is to manage all possible errors in one location and allow the application to navigate to an error-page
once any error is thrown. Now I would like to clarify that when I say error, I mean server side errors, emanating from your data end-points.
To do this, we will make use of the one place through which every HTTP
request passes in an angular application - the interceptor
. We usually make use of the interceptor to tap outgoing requests and append headers, tokens etc. But we can also tap onto the incoming response and handle the error situations.
When the next: HttpHandler
handles the request, the request is sent to the back-end server. We can pipe the observable to tap onto the incoming response.
interceptor.service.ts:
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
return next.handle(req).pipe(
catchError((error) => {
const { code, message } = error.error;
this.errorService.addError({
code: code || error?.status,
message: message || error?.statusText,
});
this.router.navigate(['/error']);
return EMPTY;
})
);
}
We also navigate to our designated error page, which is designed to handle the error code and message and display it appropriately.
Additional improvisation: Use a resolver
for the error component and check if the error observable has any value. If not then redirect to the home-page. This may be helpful when the user refreshes the error page; then it would make more sense to be taken to the home page to try again, instead of showing the same error once again.
error.resolver.ts:
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this.errorService.error$.pipe(
take(1),
tap((data) => {
if (!data) {
throw new Error('No error');
}
}),
catchError(() => {
this.router.navigate(['/']);
return of(null);
})
);
}
Cheers!
Anirban Mukherjee
Top comments (4)
As far as I understand, all errors are redirected to the
/error
path. Right? The best option is to show the error page on the path where the user went. At the moment (Angular 13) there is no such built-in feature, so we have to come up with workarounds.See solution on stackblitz
It is an interesting point. The only problem I see with this approach is the need to write an error handler inside every route resolver. That kind of makes the components lose their purpose. I believe all the user needs is to navigate back to the page where he/she came from, and for that we can make use of
@angular/common
'sLocation
class.Another approach is - (if we want to stay on the same page) - is to use
{ skipLocationChange: true }
when we navigate to/error
.No, it's not. On the contrary, we can use the components to the fullest, because we can use the appropriate component for the error handler:
Excellent articule thanks