Angular 2:如何在应用程序中强制注射器成为单例

Angular 2: how to force an injectable to be a singleton in the app

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

我知道 DI 在 angular 2 中是如何工作的,所以像 'Make sure it is added as a provider only in App Module' 这样的回答没有帮助。 :(

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

Angular 每个提供商维护一个实例。

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

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

如果您仅在 AppModuleproviders 或导入到 AppModule 的模块的 providers 中提供服务,那么您的整个实例将只有一个实例申请:

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

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

@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

Only the root AppModule should import the CoreModule. Bad things happen if a lazy loaded module imports it.