Reputation: 13
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
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
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.
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);
}
}
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