Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 5 HttpInterceptor Error Handling with calling the error handling of the caller first

I have a global HttpInterceptor with a catch block which handles an HttpErrorResponse. But my requirement is that when a service makes the http call and also has an error handler i want the error handler on the service to go off first. If there is no error handler on this service then i want the global HttpInterceptor error handler to handle it.

Example code:

Http Interceptor:

@Injectable()
export class ErrorHttpInterceptor implements HttpInterceptor {

constructor(private notificationService: NotificationService) {}

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req)
  .catch(
    error => {
      if (error instanceof HttpErrorResponse) {
        this.notificationService.error('Error', 'Error in handling Http request');
      }

      return Observable.empty<HttpEvent<any>>();
    }
  );
 }
}

And the service call:

updateUser(id, data) {
  return this.http
    .patch(`${API.userUrl}/${id}`,  {data: data})
    .subscribe(
      () => console.log('success'),
      (err) => this.notificationService.error('custom code to handle this')
     );
}

In this case the ErrorHttpInterceptor gives the notification and then the userService error handling also gives the error notification.

But In my usecase i want the ErrorHttpIntercetor to handle the error only if the underlying subscriptions didnt handle the error. Is there a way to do this?

like image 305
Nani Avatar asked Apr 09 '18 20:04

Nani


1 Answers

This is the best solution I have come up with so far.

In your interceptor, create a new subscription property on the error object, then rethrow your error:

return next.handle(authReq).pipe(
    catchError((err: any, caught: Observable<HttpEvent<any>>) => {
        err.defaultHandler = timer(0).subscribe(() => {
            this.notify.error('Server Error', 'Server Error Message');
        });
        return throwError(err);
    })
);

Where you want to actually handle the error, unsubscribe from the timer subscription created above:

this.authService.login(authRequest).subscribe((x) => {
  this.navigateDefaultRoute();
}, (err) => {
  // Prevent default error from being handled
  err.defaultHandler.unsubscribe();

  this.notify.error('Invalid Credentials', 'Email and password did not match');
});
like image 64
Chris Fremgen Avatar answered Oct 05 '22 02:10

Chris Fremgen