Angular, how to create a global custom Error Handler
In complex projects can be useful to create your own error handler in Angular. Maybe you want to log the errors in the server or present more explicits messages for the debug of the application.
As described by the official angular documentation ::The default implementation of:: ErrorHandler
:: prints error messages to the console
.::
In our example we create a custom Error handler that will be used by Angular in place of the default implementation. This is the structure of the implementation, you can customize it according to your requirements.
Create an Error class
- you need to create a class that
implements ErrorHandler
, the default implementation provided by Angular - you have to override the
handleError(error:any)
method with your own implementation
For our tutorial we created a Service, this is a common solution if you want to communicate the issue to the server. You can use a standard class
to implement you own error handler.
import { Injectable, ErrorHandler } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class MyErrorHandlerService implements ErrorHandler {
constructor() { }
handleError(error: any): void {
console.error("My error handler:\n", error);
// TODO: do something useful with the exception
}
}
Declare your handler in the module
To tell Angular that you want to catch the exceptions with your own handler you need to define the provider in the module. In our example we add the provider to the App module:
providers: [MyErrorHandlerService]
AND we need to replace the default error handler provider in the Angular internal map of dependencies : [{provide: ErrorHandler, useClass: MyErrorHandler}]
At runtime, when there will be a call to ErrorHandler
Angular will give the reference of our class MyErrorHandler
.
Our final code is:
import { NgModule, ErrorHandler } from '@angular/core';
import { BrowserModule } from "@angular/platform-browser";
// we import our service
import { MyErrorHandlerService } from "./common/my-error-handler.service";
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
],
providers: [
// we replace the default ErrorHandler
{provide: ErrorHandler, useClass: MyErrorHandlerService}
],
bootstrap: [AppComponent]
})
export class AppModule { }
We can test our error introducing a simple error:
ngOnInit(): void {
// @ts-ignore
test = test+1;
}
Without custom error Angular Core would have handled the exception for us:
Uncaught (in promise), Zone.js wrap it in a text
We had a particular situation in which our error handler was not called because Angular was throwing an Uncaught (in promise)
exception.
Zone.js caught the Exception coming from a Promise (an HTTP request returning 404) and wrapped in a string (message): "Uncaught (in promise): HttpErrorResponse: ..."
.
To disable this behaviour we had to tell Angular to don't wrap this kind of error.
In the src
directory we create a zone-flag.ts
file and added the following line:
(windows as any).__zone_symbol__DISABLE_WRAPPING_UNCAUGHT_PROMISE_REJECTION = true;
Here you can find the references in the source code zone.configurations.api.ts and promise.ts
Deep dive
You can look at the details of the implementation of ErrorHandler in the Angular source code