Volver

Forcing New Service Instance Creation. Overriding Dependency Injection in Angular

Diario del capitán, fecha estelar d43.y41/AB

Angular Development Frontend
Frontend Developer
Forcing New Service Instance Creation. Overriding Dependency Injection in Angular

In Angular, injected services are determined by various factors that we cannot always directly control. Let's see some ways of overcome them.

Learning how to force the injector to create new instances instead of using existing ones can be a solution to typical problems that arise when using singleton objects. For example, when a service maintains state and is used from multiple places simultaneously.

The proper way to inject a service into our class is perfectly documented in one of the Angular documentation guides: Introduction to services and dependency injection. This is the recommended way for most cases.

Usually, we can have sufficient control over service instances by specifying the service in components or modules through the providers attribute of these objects. For example, if at a certain point in our component and module hierarchy we want to ensure that a new instance of a service is created, we just have to declare it in that attribute.

@Component({
  standalone: true,
  selector:    'app-hero-list',
  templateUrl: './hero-list.component.html',
  providers:  [ HeroService ]
})
export class HeroListComponent {

In the above example, even though the HeroService service has been declared in a higher component or module, through the providers attribute of the component, we force the injector to create a new instance that will be used from this component downwards.

However, we cannot always or do not always want to use this method. An example is services that are instantiated at the root level and used from other services. Services do not have the providers attribute available, so it is not possible to force this instantiation from a service. It is possible that if the service is not at the root level, we can find a module or component that instantiates it, but it is not always possible.

In these cases, it is possible to use the dependency injector to force the creation of this new instance at the service level. For example, let's say we have the following two services.

@Injectable({providedIn: 'root'})
export class HeroService {
  private dataHeroService: DataHeroService = injectable(DataHeroService)
@Injectable({providedIn: 'root'})
export class DataHeroService {
  myStateNumber = 0

When using DataHeroService from HeroService we access the only instance (singleton) that exists of this service throughout the application. Since DataHeroService has internal state, there is a possibility that a third object modifies that state, thereby modifying the behavior of DataHeroService and consequently behaving unexpectedly from the point of view of HeroService.

If we wanted to ensure that HeroService gets a unique service instance that will not be shared with any other object in the application, we can do it like this.

@Injectable({providedIn: 'root'})
export class HeroService {
  private dataHeroService: DataHeroService;
  private injector = inject(Injector);

  constructor() {
    const injector = Injector.create({ providers: [DataHeroService], parent: this.injector });
    this.dataHeroService = injector.get(DataHeroService);
  }

In this example, we are using the static method Injector.create to create a new injector, to which we pass the service, or list of services, that we want to create and a reference to the current injector in order to resolve the dependencies that DataHeroService may have.

Once the new injector is instantiated, we can ask it for the instance of DataHeroService that will be unique in this context.

Compartir este post

Artículos relacionados

Change detection strategy in Angular

Change detection strategy in Angular

How to change the detection strategy in Angular to improve performance and to adapt it to your project requirements.

Leer el artículo
Comparing the three Angular view encapsulation methods

Comparing the three Angular view encapsulation methods

Since we started the company, we have been using Angular for most of our frontend development projects. In this blog post, we share how we encapsulate the views in Angular projects.

Leer el artículo
Our curated Angular reference guide

Our curated Angular reference guide

We share useful Angular resources, questions, experiences, tools, guides and tutorials to keep this curated Angular reference post up-to-date. Enjoy it!

Leer el artículo