I would like to understand the memory and performance implications of singleton vs injected services in Angular 7.
Dependencies in Angular are handled via providers. There are many types of providers such as constant values, factories, classes etc.. etc..
A service refers to an injectable class that has been instantiated. When it is instantiated depends upon when it is provided. The most common place to declare a provider is in the declaration of a module. So we refer to this as the scope of the provider.
A provider by default is a single value resolver, but it's possible to configure a provider as multiple. For simplicity sacks let's assume providers are singletons within a scope.
A scope can have a parent and children. When a provider is declared it is provided in the current scope. Modules tend to be very high up on the injector tree with the root at the top.
When a component is created we can think of that as a new scope. With the bootstrap component at the top of the component tree, but given that you can use a factory to create a new component means you shouldn't assume everything is part of the same tree.
Yeah it can get complicated.
For example, let's say that I have a list of components on a page and each one is injected the same service (i.e. it's listed in the component providers).
Let's assume this service is named FooBarService. I can explain the many different things that can happen based upon how you've configured the dependency injector.
- The injector will throw an error that
FooBarService is an unknown dependency.
- The root module has provided
FooBarService and this component and all other components will receive the same instance.
- The lazy loaded module has provided
FooBarService and this component will receive an instance, but components outside the lazy module will throw an error of unknown dependency.
- The parent component has provided
FooBarService and all its children components will receive an instance.
- Each component has provided
FooBarService and each component receives a new instance.
Since you've stated "it's listed in the component providers" then option #5 would apply.
See this reference: https://angular.io/guide/providers#providing-services-in-modules-vs-components
Does this mean that if I have e.g. 50 components, I will need 50 times the memory requirements for the injected service, vs a singleton service that is common to all?
Yes, if you have declared the provider in the scope of a component and not the scope of a module. There will be one instance per component that has declared it, but that instanced is shared for the children of that component.
Are there any other performance implications to consider?
Yes, it requires more memory and time to create 50 components if the injector has to create new instances. Will it have a negative impact on your software? As with any decision it depends upon why you are doing it. If it is to resolve a dependency problem, then it might be the only way to do it. If you can use a shared singleton service instead, then I would wonder why you weren't doing that.