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

时间:2017-01-20 14:24:34

标签: angular service singleton injectable

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

我知道DI在角度2中是如何工作的,所以答案如下:'确保它仅作为提供者添加到App Module'没有帮助。 :(

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

1 个答案:

答案 0 :(得分:7)

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

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

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

如果您仅在导入providers的{​​{1}} AppModuleproviders个模块中提供服务,那么整个应用程序只会有一个实例:

AppModule

陷阱是延迟加载的模块。如果模块是延迟加载的,那么提供的提供程序将导致创建另一个实例,因为延迟加载的模块具有自己的DI根范围。 对于延迟加载的模块,实现@NgModule({ providers: [...], imports: [...] }) export class AppModule {} 并仅在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

以外的任何地方导入此模块

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

  

只有根AppModule才能导入CoreModule。如果延迟加载的模块导入它,则会发生错误。