如何在模块中应用Angular ErrorHandler

时间:2017-09-21 17:57:24

标签: angular

这是我的Angular 4 app模块:

@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]
如果在AppComponent中抛出错误,将调用FrontExceptionHandler.handle 它不会被调用在其他模块中触发的错误,例如我的DiscussModule(在导入中)或任何模块的导入。

我希望在所有模块中触发此ErrorHandler。我有很多模块,宁愿不提供这个ErrorHandler。

我们正在迁移出angular.js,解决方案很简单:

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

在Angular 4中有没有办法做到这一点?

2 个答案:

答案 0 :(得分:0)

在angular中你可以编写拦截器来拦截http请求。所以在拦截器中你可以从一个地方处理所有http调用的错误。我会完美地为所有模块工作。

非HttpClient的

拦截器使用

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);
  }
}

HttpClient的拦截器

这是针对新的HttpClient,您可以直接编写拦截器,如下所示

@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 { }

答案 1 :(得分:0)

首先,让我们定义一个 GlobalErrorHandler 类,它将继承自 ErrorHandler ,如下所示:

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;
  }

}

现在你必须告诉Angular使用你的GlobalErrorHandler而不是默认的添加提供商到你的 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 { }