简体   繁体   English

Angular2在自定义ErrorHandler中注入服务

[英]Angular2 Injecting services in custom ErrorHandler

I have the following code : 我有以下代码:

app.module.ts: app.module.ts:

NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        RouterModule,
        BrowserModule,
        ReactiveFormsModule,
        FormsModule,
        HttpModule,
        AppRoutingModule // Routes
    ],
    providers: [ // services
        AppLog,
        {provide: ErrorHandler, useClass: MyErrorHandler}
    ],
    bootstrap: [AppComponent]
})
export class AppModule {}

MyErrorHandler.ts: MyErrorHandler.ts:

@Injectable()
export class MyErrorHandler implements ErrorHandler {
  constructor (private _appLog: AppLog) {}

  handleError(error:any):void {
    let errorMessage: string = "" + error
    this._appLog.logMessageAsJson(errorMessage, "error")
            .subscribe(
              ...
            )
  }
}

appLog.ts appLog.ts

@Injectable()
export class AppLog {
    constructor (private _http: Http) {}

    logMessageAsJson(message: string, type: string) {
        let headers = new Headers({ "Content-Type": "application/json" })
        let jsonMessage = {"type": type, "message": message}

        return this._http.post(JSON.stringify(jsonMessage), headers)
    }
}

However, when my app bootstrap, it fails if I have an injection in MyErrorHandler with the following error : 但是,当我的app bootstrap时,如果我在MyErrorHandler注入了以下错误,则会失败:

Unhandled Promise rejection: Provider parse errors:
Cannot instantiate cyclic dependency!

If I do remove constructor (private _appLog: AppLog) {} and then do something else in handleError it works just fine and the ErrorHandler is called. 如果我删除constructor (private _appLog: AppLog) {}然后在handleError执行其他操作, handleError可以正常工作并调用ErrorHandler。

I guess it doesn't work as AppLog and MyErrorHandler are instantiated at the same time 我想这不起作用,因为AppLog和MyErrorHandler同时被实例化

You can use this workaround to break up cyclic dependencies with DI 您可以使用此变通方法来分解与DI的循环依赖关系

@Injectable()
export class MyErrorHandler implements ErrorHandler {
  private _appLog: AppLog;
  constructor (injector:Injector) {
    setTimeout(() => this._appLog = injector.get(AppLog));
  }
  ...
}

Angulars DI itself just doesn't support cyclic dependencies. Angulars DI本身不支持循环依赖。

The ErrorHandler is created before the providers. ErrorHandler是在提供者之前创建的。 So we need Injector for dependency injection in our custom error handler class. 所以我们需要Injector在我们的自定义错误处理程序类中进行依赖注入。

@Injectable()
export class MyErrorHandler implements ErrorHandler{
   constructor(private injector: Injector) { } 
  handleError(error: any) {
      let router = this.injector.get(ServiceName);

    }
}

Create a default service via Angular cli and check the first part see providedIn: 'root', 通过Angular cli创建默认服务并检查第一部分,参见providedIn: 'root',

@Injectable({
  providedIn: 'root',
})
export class CustomService{
  constructor(private otherService: OtherService) { // ok not failed } 
}

For more detail check angular @Injectable-level configuration 有关更多详细信息,请检查angular @Injectable-level configuration

@NgModule-level injectors You can configure a provider at the module level using the providers metadata option for a non-root NgModule, in order to limit the scope of the provider to that module. @ NgModule级注入器您可以使用非根NgModule的providers元数据选项在模块级别配置提供程序,以便将提供程序的范围限制为该模块。 This is the equivalent of specifying the non-root module in the @Injectable() metadata, except that the service provided via providers is not tree-shakable. 这相当于在@Injectable()元数据中指定非根模块,除了通过提供程序提供的服务不是树可抖动的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM