Chris
Chris

Reputation: 13

How to apply Angular ErrorHandler accross modules

Here's my Angular 4 app module:

@NgModule({
declarations: [
    AppComponent
],
providers: [
    QuickBoardListService,
    {provide: ErrorHandler, useClass: FrontExceptionHandler}
],
imports: [
    BrowserModule,
    CommonModule,
    FormsModule,
    HttpModule,
    BrowserAnimationsModule,
    NgbModule.forRoot(),
    UpgradeModule,
    // internal
    BoardModule,
    CoreModule,
    DiscussModule,
    FormModule,
    SystemModule,
    QuickBoardModule
],
bootstrap: [AppComponent]

FrontExceptionHandler.handle will get called if an error is thrown in AppComponent It will not be called for error triggered in other modules such as my DiscussModule (in imports) or any of that module's imports.

I would like for this ErrorHandler to be triggered in all modules. I have a lot of modules, and would rather not provide this ErrorHandler in all.

We are migrating out of angular.js where the solution was simple:

$provide.decorator("$exceptionHandler", ['$delegate', '$injector',
    function ($delegate, $injector) {
        return function (exception, cause) {
            $delegate(exception, cause);

Is there a way to do this in Angular 4?

Upvotes: 0

Views: 1084

Answers (2)

Luca Ritossa
Luca Ritossa

Reputation: 1185

First, let's define a GlobalErrorHandler class that will inherit from ErrorHandler like so:

import { ErrorHandler, Injectable, Injector } from '@angular/core';
import { LoggingService } from '../services';  //<-- Replace this with your logging service or something similar

@Injectable()
export class GlobalErrorHandler implements ErrorHandler {

constructor(private injector: Injector) { }

handleError(error) {
    const loggingService = this.injector.get(LoggingService);
    const message = error.message ? error.message : error.toString();
      // log on the server
      loggingService.log({ message });
    });
    throw error;
  }

}

Now you have to tell Angular to use your GlobalErrorHandler instead of the default one adding the provider to your app.module.ts:

import { NgModule, ApplicationRef, ErrorHandler } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { GlobalErrorHandler } from './error-handler'; //<-- adapt the "from" to your file
import { ServicesModule } from './services';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  bootstrap: [AppComponent],
  providers: [
    {
      provide: ErrorHandler, 
      useClass: GlobalErrorHandler
    }
  ]
})
export class AppModule { }

Upvotes: 2

Aniruddha Das
Aniruddha Das

Reputation: 21688

In angular you can write interceptor to intercept http request. So the in the interceptor you can handle error for all http call from one place. I will work perfectly for all modules.

interceptor for non HttpClient uses

export class AppComponent implements OnInit {
      reqInterceptable: Interceptor<any[], any[]> = req => {
        if (req[1] && req[1].headers ) {
          // do what ever you want
        }

        return req;
      };

  respInterceptable: Interceptor<Observable<Response>, Observable<Response>> = res => res.do(null, e => {
    if (e.url) {
        this.alerter.alert(new DangerAlert('HTTP Error: ' + e.status + ' ' + e.statusText,
          'URL: ' + e.url, 'Info: ' + e.json().message));
    }
    return e;
  });

  constructor(private alerter: AlertService,
    public interceptor: HttpInterceptorService,
    private router: Router,
    private route: ActivatedRoute,
  ) {
    this.skipDictionary = {};
    // handled skipAlert flag for messaging of failed requests
    this.interceptor.request().addInterceptor(this.reqInterceptable);

    // for every request if we get an error notify the user of it
    this.interceptor.response().addInterceptor(this.respInterceptable);
  }
}

Interceptor for HttpClient

This is for the new HttpClient and you can directly write the interceptor like below

@Injectable()
export class HttpsRequestInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // do something for your error message
    return next.handle(dupReq);
  }
};
@NgModule({
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: HttpsRequestInterceptor, multi: true }
  ]
})
export class InterceptorModule { }

Upvotes: 0

Related Questions