Nil
Nil

Reputation: 195

Is it possible to ignore some errors conditionally, in global error handler of Angular?

I have a situation where I call an API to save data both manually and automatically,

  1. In the case of manual save I want to show the error if the save fails, and I achieved this using an angular global error handler.
  2. In the case of automatic save I want to ignore the error, but as I have a global error handler it's catching the error and showing it to the user as per the implementation.

I am trying to find a way to manage this error handling based on some conditions.

following are some code snippets for a better understating of the problem

Global error handler

 export class GlobalErrorHandlerService implements ErrorHandler  {
  constructor(private notification2Service: NotificationService,
              private loggingService: LoggingApiService) {
  }

  handleError(error: any): void {
      this.notification2Service.notify(error.message);
      this.loggingService.logError(error);
    
  }
}

Save method

    post(path: string, body: Object = {}, skipSpinner = 'false'): Observable<any> {
      let fullPath = this.getBaseApiUrl(path);
      return this.http.post(fullPath,body,{
        headers: {'skip-spinner':skipSpinner}
      });
    }

what I want is global error handler should ignore errors in this call if "skipSpinner" is 'true'

Upvotes: 2

Views: 1055

Answers (1)

Randy
Randy

Reputation: 9849

Old question but it might be useful for some people to still get this answered.

You want to implement HttpInterceptor instead of ErrorHandler. The first is for HTTP errors the latter for application errors. If the HttpInterceptor is not triggered it will go through to ErrorHandler if the exception is not caught before.

Here is one example class that intercepts HTTP errors and filters some based on StatusCode, some on the request URL and some based on headers. Feel free to use whatever you need.

Note: I might have made typo's or other mistakes, please use the general idea but make sure you implement this in a way that suits your application.

@Injectable({ providedIn: 'root' })
export class ErrorInterceptor implements HttpInterceptor {
  // I use NGRX to do stuff, feel free to use any other mechanism :)
  constructor(private store: Store) {  }
  
  const ignoredURLs = [];
  const ignoredHeaders = [];

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<any> {
    return next.handle(request)
      .pipe(
        catchError((err: HttpErrorResponse) => {
          if ([ 401 ].includes(err.status)) {
            // This error will be handled here since we do not throw, so the subscribe is triggered
            // I do let NGRX know there was an unauthorized issue, maybe we need to display a modal to the user
            this.store.dispatch(handleUnauthorized());
            return of(false);
          }
          if (this.ignoredUrls.includes(err.url)) {
            // We handle these errors from specific URL's here since these don't make the application crash
            return of(false);
          }
          if (this.ignoredHeaders.find(header => Object.keys(err.headers).includes(header))) {
            // Here you can handle the errors that have headers you want to ignore
            return of(false);
          }
          // All other errors will be thrown
          // To handle these specifically, add a pipe at the location the HTTP request was made
          // .pipe(catchError(() => { /* ... */ }));
          throw err;
        })
      );
  }
}

Upvotes: 1

Related Questions