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

Nani picture Nani · Apr 9, 2018 · Viewed 8.1k times · Source

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?

Answer

Yerkon picture Yerkon · Apr 10, 2018

One way to solve is to pass httpHeaders with request:

 request() {  
    const url = 'GoalTree/GetById/'; 
    let headers = new HttpHeaders();
    headers = headers.append('handleError', 'onService');
    this.http.get(url, {headers: headers})
      .pipe(
      map((data: any) => {
        this.showError = false; 
      }),
      catchError(this.handleError)
      )
      .subscribe(data => {
        console.log('data', data);
      })
  }

Interceptor.ts:

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    this.spinnerService.show();

    return next.handle(req).do(
      (event: HttpEvent<any>) => {
        if (event instanceof HttpResponse) {
          this.spinnerService.hide();
        }
      },
      (err: any) => {
        if (req.headers.get('handleError') === 'onService') {
          console.log('Interceptor does nothing...');
        } else {
          console.log('onInterceptor handle ', err);
        }

      }
    );
  }

and check request headers ininterceptor's error callback. But in this solution anywhere Interceptors handles request before the any service calls.

StackBlitz Example