【问题标题】:Angular 6 providedin doesn't work -> StaticInjectorErrorAngular 6 提供的不起作用-> StaticInjectorError
【发布时间】:2018-10-13 00:16:30
【问题描述】:

我正在尝试在 Angular 中使用“providedin”功能,但收到错误“StaticInjectorError(AppModule)[DashboardComponent -> DashboardService]:”

@Injectable({
  providedIn: DashboardModule
})
export class DashboardService {
  getContent() {
    return 'Dashboard Service works!!!';
  }
}

完整演示https://stackblitz.com/edit/angular-kbkjet 感谢您的努力!

【问题讨论】:

  • providedIn 不会自动注入服务,如果您想遵循该特定路线,则需要使用Injector 检索服务实例。
  • @briosheje,你是说这个stackblitz.com/edit/angular-kbkjet吗?如果没有,你能举个例子吗?
  • 不,抱歉,我没有正确解释:如果你不使用providedIn: 'root',服务不会是单例的。在您的情况下,您可以使用providedIn: 'root',或者以更简单的方式将DashboardService 添加到DashboardComponent 提供程序。
  • @briosheje 它将是每个仪表板模块实例的单例,我想这是他想要的。所以如何使它在非根级别上可摇树是真正的问题,因为@Injectable 规范确实允许除'root' 之外的其他值
  • @SIARHEIPAKHUTA 这感觉像是一个角虫。您的工作方式与here 描述的完全相同,其中明确指出In the following excerpt, the @Injectable decorator is used to configure a provider that will be available in any injector that includes the HeroModule.

标签: angular


【解决方案1】:
  • 98% 的情况下,使用 providedIn = 'root'。它将向根应用程序注入器注册服务,将被摇树,并将可供任何需要它的组件使用。摇树将确保服务仅包含在使用它的捆绑包中。
  • 如果只需要在组件及其嵌套子项中提供服务,则在组件中使用 providers 数组。 (用于组件级别的服务隔离,或者每个组件需要多个服务实例。)
  • 不要在模块中使用 providers 数组(这是旧语法,不再推荐)
  • 如果您想限制对特定延迟加载模块的服务访问,请使用 providedIn='lazymodule'。然后它将需要一个额外的模块来防止循环依赖问题。这提供了模块级别的服务隔离。如果此延迟加载模块之外的应用程序中的任何其他组件尝试引用该服务,则会生成“超出注入器范围”错误。

有关“附加模块”的更多信息,请参阅此:https://www.youtube.com/watch?v=jigR_jBhDMs&feature=youtu.be

此处的示例代码:https://github.com/web-dave/provide-in-test

这里讨论循环依赖问题:https://github.com/web-dave/provide-in-test/issues/1

【讨论】:

  • 谢谢!我不知道“lazymodule”选项。我看到其他人使用“解决方法”,其中涉及创建一个名为 ServiceModule 的空模块来避免循环依赖。似乎没有达到目的,因为在 LazyModule 级别使用 providers[ ] 会产生相同的结果。
  • 但它不会产生相同的结果。使用提供者数组不支持摇树。所以任何未使用的代码都不会被删除。也许这对您的特定项目来说不是问题?
  • 啊,好吧,我想我知道我哪里出错了。我对树抖动有更广泛的定义,其中包括延迟加载。我的困惑可能来自这样一个事实,providedIn 不仅为我们提供了 Tree Shaking(删除死代码),而且还允许我们延迟加载(应用程序范围的)单例服务,因为提供者数组迫使我们将应用程序范围的单例服务放在我们的 main 中。 js 捆绑包。在我看来,如果您在惰性模块中提供服务,那么您肯定在使用它。因此,在这种情况下,解决方法似乎毫无意义,因为您不会提供死代码。
  • @DeborahK 我正面临延迟加载模块场景,当然我会收到循环 deps 警告,但我的服务也有 no provider 错误,它仅用于延迟加载模块的组件,据我所知,注入器应该可以很好地提供服务。创建额外的LazyServiceModule 可以解决循环依赖和no provider。我错过了什么?
  • 您是否查看过上面“此处的示例代码”链接中提供的示例代码?你的代码类似吗?
【解决方案2】:

Stepan Suvorov 发布的stackblitz example 在使用时不起作用

providedIn: AppModule

因为依赖问题,导致AppModule 未解决(未定义)。

如果您在@Injectable 装饰器上方添加console.log(AppModule),则输出为undefined

注意 您实际上看不到 stackblitz 上的依赖问题,但如果您在本地 Angular cli 上复制项目,您会看到以下警告。

检测到循环依赖中的警告: src\app\app.component.ts -> src\app\my.service.ts -> src\app\app.module.ts -> src\app\app.component.ts

检测到循环依赖中的警告: src\app\app.module.ts -> src\app\app.component.ts -> src\app\my.service.ts -> src\app\app.module.ts

检测到循环依赖中的警告: src\app\my.service.ts -> src\app\app.module.ts -> src\app\app.component.ts -> src\app\my.service.ts

我认为在providedIn 中使用AppModule 没有任何意义,您不妨使用root。但是如果你希望你的服务只在子模块中提供,这应该像stackblitz demo

这是related github issue

注意:在声明一个可注入服务时,如果你使用providedIn和一个模块值,指定的模块不能是声明一个使用该服务的组件的模块(相当拗口)

【讨论】:

    【解决方案3】:

    确保您在测试中导入了这样的模块:

    beforeEach(() => TestBed.configureTestingModule({
      imports: [DashboardModule]
    }));
    

    【讨论】:

      【解决方案4】:

      终于找到了解决办法:https://angular.io/guide/providers#providedin-and-ngmodules 服务也应该在模块的提供者部分提及。

      @NgModule({
        imports: [CommonModule],
        declarations: [DashboardComponent],
        exports: [DashboardComponent],
        providers: [DashboardService]
      })
      

      Demo 已更正。 谢谢各位!

      【讨论】:

      • 其实你展示的链接是提供服务的两种方式。第一种方法是因为一个奇怪的原因而失败。所以是的,添加到提供者工作,但你失去了摇树的能力
      • @PierreDuc 你是什么意思“奇怪的原因”?您能否提供一个示例,如何使用不在根(应用程序)级别的服务并保持摇树的能力?附言我看过你的原始问题的帖子。所以,你认为这是一个 Angular 错误。也许吧,但我不敢相信谷歌团队失败了))))
      • 通过使用 providedIn: DashboardModule 而不是将其添加到模块的 providers 数组中。但不知何故,角度是愚蠢的。你在运行最新版本吗,因为这真的感觉像一个错误
      • 我使用 Angular 6.0.4 版本
      • 演示代码中使用的是6.0.7,是最新版本
      猜你喜欢
      • 2018-11-29
      • 1970-01-01
      • 2019-03-26
      • 2019-02-25
      • 1970-01-01
      • 2018-12-23
      • 1970-01-01
      • 1970-01-01
      • 2018-05-09
      相关资源
      最近更新 更多