我的应用程序中有一个 @Injectable 服务,它被添加为 AppModule 中的提供者。我想确保我的开发团队中没有人将它注入(inject)任何其他模块。一个实例就足够了,它有一些复杂的逻辑,我不想运行两次。有任何想法吗?

我知道 DI 在 angular 2 中是如何工作的,因此诸如“确保它仅作为提供程序添加到 App 模块中”之类的答案无济于事。 :(

请注意,如果该服务提供给除 AppModule 之外的任何其他服务,我希望它在构建或运行时产生某种错误。

最佳答案

Angular 为每个提供者维护一个实例。

确保您只提供一次服务,DI 将确保您的应用程序中只有一个实例。

如果您在组件 @Component({ ..., providers: [...]}) 上提供服务,那么实例数量将与组件实例一样多。

如果您仅在 providersAppModule 或导入到 providers 的模块的 AppModule 中提供服务,那么您的整个应用程序将只有一个实例:

@NgModule({
  providers: [...],
  imports: [...]
})
export class AppModule {}

一个陷阱是延迟加载模块。如果模块是延迟加载的,那么提供的提供程序将导致创建另一个实例,因为延迟加载的模块有自己的 DI 根范围。
对于延迟加载的模块,实现 forRoot() 并添加仅在 forRoot() 中应该是应用程序范围的单例的提供程序,而不是在 providers 中并在 AppModule 中导入它

@NgModule({
  providers: [...],
  imports: [LazyLoadedModuleWithSingltonProvider.forRoot()]
})
export class AppModule {}

更新

为了防止实例化一个服务的多个实例,您可以使用类似的解决方法

@Injectable()
export class MyService {
  private static instanceCounter = 0;
  private instanceNumber = instanceCounter++;

  constructor() {
    if(this.instanceNumber > 0) {
      throw 'MyService must be kept a singleton but more than one instance was created';
    }
  }
}

另一种方法是将单例服务移动到 CoreModule 并防止将此模块导入到 AppModule 之外的任何其他地方

https://angular.io/docs/ts/latest/guide/ngmodule.html#!#prevent-reimport

关于 Angular 2 : how to force an injectable to be a singleton in the app,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41765854/

10-09 06:23