2015-11-06 4 views
26

Wie würde ich einen Dienst in einen anderen einspeisen? Lassen Sie uns zum Beispiel sagen, dass ich eine Sammlung habe, die eine andere Sammlung erfordert (TeamCollection => PlayerCollection). Derzeit erstelle ich nur zwei getrennte Sammlungen und nutzen so etwas wie:Angular2 "Services" wie @in einen Dienst in einen anderen einspeisen (Singletons)

import {PlayerCollection} from "<<folder>>/player"; 

Aber dies erfordert mir meine eigenen Singleton getInstance-Code in Maschinenschrift für jeden Dienst zu schreiben, dass ich eine Singleton-Instanz sein wollen.

Was ist der richtige Weg, dies zu tun? Ich möchte beide Singletons innerhalb meiner Komponenten haben und in der Lage sein, @ einen Dienst unter Verwendung der Konstruktorsyntax in einen anderen zu injizieren, ohne eine neue Instanz der Singletons zu erzeugen.

class TeamCollection {  
    constructor(@Inject(PlayerCollection): PlayerCollection) {} 
} 

Antwort

15

So nach erneuter Lektüre dieses ausgezeichneten Beitrag von Pascal Precht: http://blog.thoughtram.io/angular/2015/05/18/dependency-injection-in-angular-2.html

Und da ihn kommentieren: http://twofuckingdevelopers.com/2015/04/angular-2-singleton-service/

„Alles, was mit injiziert DI Angular 2 ist bereits ein Singleton Kein Bedarf an. so ein Service "

Ich ging testen, und was ich jetzt gefunden habe beantwortet meine Frage und machte mich noch mehr verwirrt über das Thema DI in angular2.

Siehe den folgenden Code:

team.ts

import {BaseCollection, BaseModel} from "./base"; 
import {PlayerCollection} from './player'; 
import {Injectable, Inject} from "angular2/angular2"; 

@Injectable() 
export class TeamCollection extends BaseCollection { 
    playerCollection: PlayerCollection; 
    constructor(@Inject(PlayerCollection) playerCollection: PlayerCollection) { 
     super(); 
     this.playerCollection = playerCollection; 
    } 

    create(data: Object): TeamModel { 
     return new TeamModel(data); 
    } 
} 

player.ts

import {BaseCollection, BaseModel} from "./base"; 
import {Injectable} from "angular2/angular2"; 

@Injectable() 
export class PlayerCollection extends BaseCollection { 
    create(data: Object): PlayerModel { 
     return new PlayerModel(data); 
    } 
} 

team.spec.ts

/// <reference path="../../typings.d.ts" /> 

//VERY IMPORTANT TO ALWAYS LOAD THESE 
import 'zone.js'; 
import 'reflect-metadata'; 
import 'es6-shim'; 

import {TeamModel, TeamCollection} from "../../app/model/team"; 
import {PlayerCollection} from "../../app/model/player"; 
import {Inject, Injector} from "angular2/angular2"; 

describe('TeamCollection',() => { 
    var teamCollection: TeamCollection; 
    var playerCollection: PlayerCollection; 
    beforeEach(() => { 
     var injector = Injector.resolveAndCreate([ 
     TeamCollection, 
     PlayerCollection 
     ]); 
     teamCollection = injector.get(TeamCollection); 

     var injectorT = Injector.resolveAndCreate([ 
     PlayerCollection 
     ]); 
     playerCollection = injector.get(PlayerCollection); 
    }); 

    it('should have a singleton PlayerCollection shared between all classes within the application',() => { 
    console.log(teamCollection.playerCollection.uuId); 
    console.log(playerCollection.uuId); 
    }); 
}); 

Solange es war der gleiche Injektor (var injector), die beide erstellt haben sie die gleiche UUID teilen Wenn ich einen zweiten Injektor (var injectorT) verwenden, sind die UUIDs anders, was bedeutet, dass eine neue Instanz der playerCollection erstellt wird.

Jetzt wäre meine Frage. Wenn ich die Syntax des Komponentenanbieters verwende:

Würden beide die gleiche Playersammlung teilen oder würden beide eine neue Instanz erstellen?

Bearbeiten: Sie tun, solange sie durch die bootstrap(.., [ServiceA,ServiceB]) Methode erstellt werden.

Dank pascal precht http://blog.thoughtram.io/angular/2015/09/17/resolve-service-dependencies-in-angular-2.html

+0

Also .. eine Idee, wie Sie den Dienst innerhalb des anderen Dienstes verwenden, nachdem Sie Http verwendet haben, um Metadaten zu erstellen? Ich habe versucht, sein Beispiel, das ist in der Verbindung an der Unterseite, aber ich verstehe nicht, wie das den Dienst in einen anderen Dienst injiziert, oder wie Sie es verwenden .. Verwirrende Sachen. – Chrillewoodz

+0

@Chrillewoodz Wenn Sie meinen, wie Sie einen Dienst in einen anderen injizieren sollen, nachdem Sie ihn der Bootstrap-Methode hinzugefügt haben. Das ist ziemlich einfach, wenn Sie Typoskript verwenden. Man schreibt es einfach in den Konstruktor: '' constructor (private http: Http) {} " –

+0

Das habe ich ausprobiert, aber der Dienst endete immer als leeres Objekt, obwohl der Dienst viele Funktionen enthielt. Ich weiß nicht warum Ich glaube auch, dass es eine sauberere Möglichkeit geben muss, Dienste in einen anderen Dienst als die Bootstrap - Methode zu injizieren. Die Bootstrap - Methode wird wirklich schnell unordentlich, was seltsam erscheint. – Chrillewoodz

1

fand ich, dass ein anderer Weg, um einen Singleton-Dienst zu haben, ist das Singletonmuster mit einem getInstance() -Methode durch die Schaffung, die den Konstruktor aufruft, dann spritzen Sie nicht Ihren Dienst den Komponentenkonstruktor, sondern verweisen Sie nur als statische Klasse. Sie können hier Beispielcode überprüfen:

Access key data across entire app in Angular 2 & Ionic 2

Blick auf meine Antwort, ich glaube, seine die zweite in der Seite.Wenn es für Sie funktioniert, würde ich mich freuen, wenn Sie es abstimmen könnten. Vielen Dank.

+3

Das ist ein Anti-Pattern: -/ –

+0

Ich rate tatsächlich davon ab, ein Standard-Singleton-Muster zu verwenden (zumindest wenn wir über eckige Dienste sprechen) Wenn Sie sich entscheiden, einen Dienst zu bauen, den Sie in anderen Projekten verwenden gehen Sie natürlich auch diese Route hinunter. –

1

Was müssen Sie sicherstellen, ist die folgende:

Sie können nur den Service injizieren, sobald Sie „zur Verfügung gestellt“, um den Dienst haben. Wenn Sie dies in einer @ Komponent tun, ist es einfach, weil Sie die Anweisungen des Providers [...] haben.

Wenn Sie dies für einen Dienst tun wollen Sie nicht die Anbieter haben: [] .... so der einzige Ort, dies zu tun während der Bootstrap-Zeit ist, wo Sie den Dienst in

boostrap(app, [ 

PlayerCollection, 
Other, 
More Services... 



] 
angeben müssen

Wenn Sie in der Dokumentation graben, sagt es speziell, dass Sie es auf diese Weise tun müssen.

+3

Ich habe festgestellt, dass Ihr Vorschlag die Frage nicht richtig behandelt. Können Sie speziell auf die Dokumentation verweisen und eine Suchzeichenfolge für die Abfrage der Seite bereitstellen? –

Verwandte Themen