我的应用程序中有一项@Injectable
服务作为提供程序添加到AppModule
. 我想确保我的开发团队中没有人将它注入任何其他模块。一个实例就足够了,它有一些我不想运行两次的复杂逻辑。有任何想法吗?
我知道 DI 在 Angular 2 中是如何工作的,所以像“确保它仅在 App Module 中作为提供者添加”这样的答案将无济于事。:(
请注意,如果该服务提供给除 AppModule 之外的任何其他服务,我希望它在构建或运行时产生某种错误。
我的应用程序中有一项@Injectable
服务作为提供程序添加到AppModule
. 我想确保我的开发团队中没有人将它注入任何其他模块。一个实例就足够了,它有一些我不想运行两次的复杂逻辑。有任何想法吗?
我知道 DI 在 Angular 2 中是如何工作的,所以像“确保它仅在 App Module 中作为提供者添加”这样的答案将无济于事。:(
请注意,如果该服务提供给除 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';
}
}
}
另一种方法是将单例服务移动到 aCoreModule
并防止将此模块导入到除AppModule
https://angular.io/docs/ts/latest/guide/ngmodule.html#!#prevent-reimport
只有根 AppModule 应该导入 CoreModule。如果延迟加载的模块导入它,就会发生不好的事情。