web-dev-qa-db-fra.com

AngularJs 2 - plusieurs instances de service créées

J'ai créé le service AngularJS 2 et je l'utilise dans 2 composants différents: App-Component & Sub-Component. Chaque propriété de sortie "log" (une chaîne) de mon service.

Classe StateService:

@Injectable ()
class StateService {

    public log : string;
    static count : number = 0;

    constructor () {
        this.log = '';
        StateService.count++;
        this.writeToLog ('CREATED '+StateService.count+' at ' + new Date().toString());
    }

    public writeToLog (text : string) : void {
        this.log += text + '\n';
    }
}  

Composant:

@Component ({
    selector : 'Sub-Component',
    template : `<hr>
            This is the Sub-Component !
            <BR>
            StateService Log : 
            <pre>{{ _stateService.log }}</pre>
            <button (click)="WriteToLog ()">Write to log</button>
            `,
    providers : [StateService]
})

export class SubComponent {
    constructor (private _stateService : StateService) {
    }

    public WriteToLog () : void {
        this._stateService.writeToLog ('From Sub-Component - This is '+new Date().toString());
    }
}

Exemple de code en direct ici

Sauf que le service est créé une fois et lorsque chaque composant appelle la méthode WriteToLog, la sortie est la même dans chaque composant, mais ce n'est pas le cas.

Exemple de sortie:

Le composant d'application peut produire ceci:

Instance 1 - Créé le jeu 21 janvier 2016 11:43:51

De App-Component - Jeu 21 janvier 2016 11:43:54

De App-Component - C'est le jeu 21 janvier 2016 11:43:55

et le sous-composant peut produire ceci:

Instance 2 - Créé le jeu 21 janvier 2016 11:43:51

De la sous-composante - c'est le jeu 21 janvier 2016 11:43:57

De la sous-composante - c'est le jeu 21 janvier 2016 11:43:58

Il apparaît donc que 2 instances de service sont créées (instance 1 + instance 2)

Je ne veux qu'une seule instance;) et lorsque j'ajoute une chaîne dans le journal, cela doit apparaître dans les deux composants.

Merci de votre aide

27
Philippe sillon

update Angular> = 2.0.0-RC.6

N'ajoutez pas le service aux fournisseurs du composant. Ajoutez-le à la place

@NgModule({ providers: [...], ...

(d'un module qui n'est pas chargé paresseusement car les modules chargés paresseux introduisent leur propre portée)

@Component ({
    selector : 'Sub-Component',
    template : `<hr>
            This is the Sub-Component !
            <BR>
            StateService Log : 
            <pre>{{ _stateService.log }}</pre>
            <button (click)="WriteToLog ()">Write to log</button>
            `,
    // providers : [StateService] <== remove
})

Angulaire <= 2.0.0-RC.5

Si vous l'ajoutez à un composant, vous obtenez une nouvelle instance de service pour chaque instance de composant. Ajoutez-le à la place

bootstrap(AppComponent, [StateService]);

Vous pouvez avoir un contrôle plus fin en l'ajoutant à un seul composant, puis ce composant et tous les enfants obtiennent la même instance injectée mais sinon l'application fonctionne avec l'instance créée par bootstrap(). Il s'agit de la "hiérarchie" dans Angulars DI.

Voir également
- http://blog.oughttram.io/angular/2015/05/18/dependency-injection-in-angular-2.html
- http://blog.oughttram.io/angular/2015/09/17/resolve-service-dependencies-in-angular-2.html

32
Günter Zöchbauer

En plus de la grande réponse de Günter, ce lien pourrait peut-être donner plus de détails sur le fonctionnement de l'injection de dépendance hiérarchique d'Angular2:

3
Thierry Templier