Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 DI - initializing multiple different instances in the same constructor

I have an Angular2 DI question. Say I have a TestService and I want to use 2 different instances of this service inside the same component. If I simply add a provider to the component and I add the 2 instances to the constructor I end up with the same service instance. For example:

TestService

import {Injectable} from "@angular/core";

@Injectable()
export class TestService {

    public id: number = Math.random();

    public toString(): string {
        return "Id: " + this.id;
    }
}

Test component

import {Component, Input, OnInit} from "@angular/core";
import {TestService} from "../../services/test.service";

@Component({
    providers: [TestService]
})
export class TestComponent implements OnInit {

    constructor(private _testService1: TestService, private _testService2: TestService) { };

    ngOnInit() {
        console.log("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", this._testService1.toString());
        console.log("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB", this._testService2.toString());
    }
}

Result in console

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Id: 0.24242492129168425
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB Id: 0.24242492129168425

Can someone pls tell me if there's a way to use Angular2's DI mechanism to inject multiple different instances of a service within the same component or should I just drop the DI for this particular case and create my instances manually with a manual constructor?

Thanks in advance

like image 851
RVP Avatar asked Jul 05 '16 22:07

RVP


People also ask

Does Angular create multiple instances of service?

Now it is a service that can be used between parent and child components. In this case, service is a non-singleton nature. It will create multiple instances of a service. Every time a new instance of provided service will be created when a component is used inside another component.

What is@ injectible in Angular?

@Injectable() lets Angular know that a class can be used with the dependency injector. @Injectable() is not strictly required if the class has other Angular decorators on it or does not have any dependencies.

How does DI work in Angular?

Dependency injection (DI) is a paradigm. The way it works in Angular is through a hierarchy of injectors. A class receives its resources without having to create or know about them. Injectors receive instruction and instantiate a service depending on which one was requested.

How many instances are created for a service in Angular?

In this article we'll explore when and why Angular creates two instances of the same service and what solutions exist to ensure a service remains a singleton in the entire application.

How to resolve constructor parameters with the same type in angular?

Angular DI maintains a single instance per provider. In your case if you have two constructor parameters with the same type, they resolve to the same instance. What you can do is to provide a factory function (different from a simple useFactory provider event though it uses it as well) If you have a fixed number of instances this should work:

How many instances does @angular di maintain per provider?

Angular DI maintains a single instance per provider. In your case if you have two constructor parameters with the same type, they resolve to the same instance.

Why does @angular create new instances for each injectiontoken or injectable?

Angular will create new instances for any of InjectionToken or Injectable in cases of using: This is happening because Angular creates a new module Injector for any lazy loaded module, this behavior is perfectly described in docs and this article.

What is the use of di in Angular 2?

Any consumers of those classes also do not need to know anything. DI saves classes and consumers alike from having to know more than necessary. Yet the code is as modular as it was before thanks to the mechanisms supporting DI in Angular. Services are a key benefactor of DI.


1 Answers

You can inject a factory that returns a new instance every time you call it:

@NgModule({
   providers: [{
      provide: 'testService', 
      useFactory: (/* TestService deps here like `http`*/) => 
        (/* params */) => new TestService(/* http */), 
      deps: [/* TestService deps here like `Http`*/ ]
    }]
})


@Component(...)
export class TestComponent implements OnInit {

    constructor(@Inject('testService') private _testServiceFactory) { };

    ngOnInit() {
        console.log("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", this._testServiceFactory( /* params */).toString());
        console.log("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB", this._testServiceFactory().toString());
    }
}

Plunker example (check the output in the browser console when you click the button)

like image 140
Günter Zöchbauer Avatar answered Nov 15 '22 16:11

Günter Zöchbauer