我的应用程序中有一个 @Injectable
服务,它被添加为 AppModule
中的提供者。我想确保我的开发团队中没有人将它注入(inject)任何其他模块。一个实例就足够了,它有一些复杂的逻辑,我不想运行两次。有任何想法吗?
我知道 DI 在 angular 2 中是如何工作的,因此诸如“确保它仅作为提供程序添加到 App 模块中”之类的答案无济于事。 :(
请注意,如果该服务提供给除 AppModule 之外的任何其他服务,我希望它在构建或运行时产生某种错误。
最佳答案
Angular 为每个提供者维护一个实例。
确保您只提供一次服务,DI 将确保您的应用程序中只有一个实例。
如果您在组件 @Component({ ..., providers: [...]})
上提供服务,那么实例数量将与组件实例一样多。
如果您仅在 providers
的 AppModule
或导入到 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/