【问题标题】:Possible to manual inject NgZone?可以手动注入 NgZone 吗?
【发布时间】:2019-11-22 05:14:19
【问题描述】:

我正在尝试使用 Injector 注入我的组件/服务,但其中之一需要 NgZone 作为其依赖项。来自https://angular.io/api/core/Injector

export MyComponent{
  constructor() {
    const injector = Injector.create({
      providers: [
        { provide: NgZone, deps: [ ] },
        { provide: MyService, deps: [ NgZone ] }
      ]
    });

    this.myService = injector.get(MyService);
  }
}

然后在子类中:

export MyOtherComponent extends MyComponent {
  constructor() {
    super();
  }

  public helloWorld() {
     this.myService.stuff();
  }
}

但我收到以下错误:

错误错误:StaticInjectorError[MyService -> NgZone]:
NullInjectorError:没有 NgZone 的提供者! 在 NullInjector.get (core.js:8896)

我尝试了一个在构造函数中没有任何内容的虚拟服务,并且它有效。

  • 有没有办法像这样通过deps 手动提供NgZone
  • 还有其他方法可以获取“全局”NgZone 对象(应该只有 1 个 NgZone 实例在运行吗?)

MyService 也是降级服务,在 AngularJS 和 Angular7 中都使用,不确定是否会改变。

编辑:我尝试这样做的原因是因为MyComponent 是一个组件基类,它将获得extends 并且有许多子类在其上扩展。如果我可以通过在内部手动注入来做到这一点,那么我不需要从孩子那里传递所有这些依赖项。想象一下,我有 6-7 个依赖项和 30 多个子项,假设我需要一些新的依赖项,我必须更新它们中的每一个...

【问题讨论】:

  • 请展示更多关于这个东西的代码。您正在创建一个没有父级的 Injector,因此它只有您给它的东西。另外,您为什么要这样做,为什么不在构造函数中注入您的服务?手动创建注入器的目的是什么?
  • 我在编辑中添加了我的理由。代码真的是你在那里看到的,我只是想知道如何手动注入任何需要那些与角度相关的类的东西,比如NgZone

标签: angular7


【解决方案1】:

你可以注入注入器——这将是一个单一的依赖。然后,您所有的孩子都可以从这个注射器中得到他们需要的东西。是的,您需要通过 super() 调用的继承链提供该注入器,但至少它只是一件事。

还有这个:

https://github.com/angular/angular/issues/16566#issuecomment-338188342

此评论指出,如果您装饰抽象类,则可以在抽象类中使用 DI。至于 NgZone 实例——是的,我相信肯定只有一个,我也尝试过一次,但无法提出一个优雅的解决方案。

【讨论】:

  • 我已经知道了,这不是我想要的。我正在探索这里的可能性。
  • 注射器是分层的,你不能得到不存在的东西。如果你只需要 NgZone - 有像这样的讨厌的 hack:stackoverflow.com/questions/47619350/… 你也可以通过一些手写的补丁自己将它存储在窗口中
【解决方案2】:

我猜我昨晚脑死了。今天早上在深入挖掘之后,我想我找到了一种获取全局区域的方法,并且它似乎有效(它触发了更改检测)。

由于@waterplea 也假设应该只有 1 个 NgZone 实例,所以我决定在控制台中查看一下,你知道什么。

然后我尝试像这样将全局区域传递给它:

    { provide: NgZone, useValue: Zone },

它给了我this.ngZone.runundefined 的错误。好的...深入挖掘,哦,嘿,Zone 中有一个root 对象,嘿,看,一个run 函数!

所以我去更新代码到这个并且它工作了。

    { provide: NgZone, useValue: Zone.root },

【讨论】:

  • 那不是 NgZone,那是 Zone。它甚至似乎不等于 (===) 到 ngZone._outer,尽管它看起来几乎相同(也称为 <root>)。如果它对你有用,那很酷,但我不建议在生产中依赖它。如果你真的需要,最好将 ngZone 存储在某个在 APP_BOOTSTRAP_LISTENER 内部初始化的单例服务的静态属性中。
猜你喜欢
  • 1970-01-01
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 2016-03-16
  • 2016-10-17
  • 1970-01-01
  • 2014-12-26
  • 2011-05-20
相关资源
最近更新 更多