【问题标题】:Angular: Injecting router in constructor giving errorAngular:在构造函数中注入路由器给出错误
【发布时间】:2019-04-26 21:30:07
【问题描述】:

我正在尝试创建一个全局错误处理组件,为此,我提供了自定义 ErrorHandler 类。我想通过 error.service.ts 中的构造函数注入路由器,以便我可以导航到错误组件,但它失败并出现以下错误。

compiler.js:18429 未捕获错误:提供程序解析错误: 无法实例化循环依赖! ApplicationRef ("[ERROR ->]"): in NgModule AppModule in ./AppModule@-1:-1

这里是项目的链接。 https://stackblitz.com/edit/angular-q56xm8

请检查 error.service.ts,如果我取消注释第一个实现,它可以工作,但我想使用以下方法使其工作。

【问题讨论】:

  • 你不能使用第二种方法,因为错误消息中写的问题:会有一个循环依赖:路由器直接或间接需要错误句柄和错误处理程序需要路由器。只需使用第一种方式:这是处理问题的正确方式。
  • 如果我在组件构造函数中注入但在服务中不起作用,请您详细说明一下它是如何工作的。
  • 好吧,你可以在组件中注入路由器,因为路由器的依赖项中没有你的组件。所以这不会产生循环依赖。但是路由器需要错误处理程序。因此,如果错误处理程序也需要路由器,则会产生循环依赖。

标签: angular inject


【解决方案1】:

让我们通过一个注册自定义错误处理程序时内部发生的示例来尝试理解这一点。

要注册错误处理程序,您可以执行以下操作:

class MyErrorHandler implements ErrorHandler {
  handleError(error) {
    // do something with the exception
  }
}

@NgModule({
  providers: [{provide: ErrorHandler, useClass: MyErrorHandler}]
})
class MyModule {}

现在所做的是,它现在使用您的 MyErrorHAndler 类而不是 Angular 的 ErrorHandler

假设在路由器的情况下,它需要一个MyErrorHandler 服务的实例来创建它自己的实例。所以注入器会寻找MyErrorHandler的实例来创建Router的实例。

Injector 没有MyErrorHandler 服务的实例(而不是常规的ErrorHandler),因此它会尝试创建一个实例,以便将其提供给Router。但是一旦它尝试创建MyErrorHandler 的实例,它就会看到MyErrorHandler 的构造函数中有Router。因此它将检查Router 的实例,它可能会注入MyErrorHandlerconstructor。但它找不到,因为 Router 是它一开始就试图实例化的东西。

TL;DR;: 为了创建Router 的实例,Angular 需要MyErrorHandler 的实例。为了创建MyErrorHandler 的实例,它需要Router 的实例。这会造成MyErrorHandler 依赖于RouterRouter 依赖于MyErrorHandler 的情况,从而产生循环依赖。

修复:正如您自己完成的,修复是使用Injector。当你使用它时,为了创建 MyErrorHandler 的实例,Angular 将不再需要在其中注入 Router 的实例。因此在这种情况下不会出现任何循环依赖的情况。

【讨论】:

  • 如果它是像 @NgModule({ providers: [ MyErrorHandler] }) 这样的普通提供者,实例化会如何发生
  • 好吧,这本来是正常的。 Angular 的 Injector 会被要求创建一个 MyErrorHandler 的实例,它会检查它是否已经有一个。如果不是,它将检查MyErrorHandler 需要实例化的所有内容,并将它们提供给MyErrorHandler 的构造函数,并最终创建MyErrorHandler 的实例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-25
  • 1970-01-01
  • 2017-07-21
  • 2020-09-09
  • 1970-01-01
相关资源
最近更新 更多