I have an @Injectable
service in my application that is added as a provider in AppModule
. I want to make sure no one in my development team injects it in any other module. A single instance is enough and it has some complicated logic that I don't want to be run twice. Any ideas?
I know how DI works in angular 2, so answers like 'Make sure it is added as a provider only in App Module' won't help. :(
PLEASE NOTE, that I want it to produce some sort of error at build or run time if the service is provided to any other but AppModule.
Angular maintains a single instance per provider.
Ensure you provide a service only once and DI will ensure that there is only one single instance in your application.
If you provide a service on a comonent @Component({ ..., providers: [...]})
, then there will be as many instances as component instances.
If you provide a service only in providers
of AppModule
or providers
of modules imported to AppModule
, then there will only be a single instance for your whole application:
@NgModule({
providers: [...],
imports: [...]
})
export class AppModule {}
A pitfall are lazy loaded modules. If a module is lazy loaded then providers provided there will cause another instance to be created, because lazy loaded modules have their own DI root scope.
For lazy loaded modules implement forRoot()
and add providers that should be application-wide singletons only in forRoot()
, but not in providers
and import it in AppModule
@NgModule({
providers: [...],
imports: [LazyLoadedModuleWithSingltonProvider.forRoot()]
})
export class AppModule {}
update
To prevent instantiation of multiple instances of a service you can use a workaround like
@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';
}
}
}
Another way is to move singleton services to a CoreModule
and prevent this module being imported anywhere else than in the 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With