2016-06-30 14 views
2

Dies ist wahrscheinlich ein spezieller Fall (das native Window-Objekt des Browsers wird injiziert), aber ich bin ein wenig verwirrt darüber, warum ich den @Inject() Parameter-Decorator noch brauche, wenn meine Klasse bereits einen @Injectable() Decorator hat.Warum brauche ich @inject in diesem angular2-Beispiel?

Nehmen Sie dieses vereinfachtes Beispiel:

import { provide, bootstrap, Injectable, Inject } from '@angular/core'; 


@Injectable() 
export class Token { 
    private token: string; 

    public constructor(token: string, window: Window) { 
    this.token = window.atob(token); 
    }; 

    public getToken(): string { 
    return this.token; 
    } 
} 


@Injectable() 
export class TokenFactory { 
    private window: Window; 

    public constructor(window: Window) { 
    this.window = window; 
    } 

    public createToken(token: string): Token { 
    return new Token(token, this.window); 
    } 
} 


@Component({ 
    template: ` 
    <p *ngFor="let token of tokens"> 
     Encoded: {{token.getToken()}} 
    </p> 
    `, 
    providers: [ TokenFactory ] 
}) 
class MainComponent { 
    public tokens: Token[]; 

    public constructor(factory: TokenFactory) { 
    this.tokens = [ 
     factory.create('token-1'), 
     factory.create('token-2') 
    ]; 
    }; 
} 


bootstrap(
    MainComponent, [ 
    provide(Window, { useValue: window }) 
]); 

Übersicht: Wir Token Klasse, die ein Objekt darstellt, das mehrere Male innerhalb einer Komponente oder einen anderen Dienst (also keine Singleton) existieren könnte. Die Tokenklasse hängt vom globalen Fensterobjekt ab (z. B. für die base64-Codierung). Um dies testbar zu machen, definieren wir einen App-weiten Provider für das globale window object während des Bootstrap, anstatt es direkt im Token-Dienst zu verwenden.

Die Hauptkomponente muss Tokens dynamisch erstellen, also erstellen und injizieren wir einen einfachen Factory-Service TokenFactory, der auch den Fensterprovider benötigt (um ihm während der Konstruktion die Tokenklasse zu übergeben).

Das Problem: Dies schlägt fehl, wenn in einem Browser mit dem Fehler ausgeführt

Can't resolve all parameters for TokenFactory: (?). 

aber kann durch Zugabe eines @Inject (Fenster) Dekorateur an die Fabriken Konstruktor Fenster Parameter festgelegt werden.

Jetzt bin ich ein wenig verwirrt, da die meisten Leitfäden/Tutorials erklären, dass der Injekt Dekorator nicht in Typoskript erforderlich ist, wenn die Klasse mit dem Injectible Decorator, , dekorieren also warum schlägt das Beispiel ohne @Inject() Dekorateur?

Config:emitDecoratorMetadata und experimentalDecorators Einstellungen aktiviert sind, und ich bin tsc 1.8.10 und angular2 rc.3 verwenden.


PS:Ich bin auch für die allgemeine Design-Verbesserungen offen.

(z. B. in einem Produktionsszenario würde ich wahrscheinlich nur die Token-Schnittstelle exportieren und nicht die ganze Klasse)

+0

Können Sie mehr darüber erfahren, wo die Window-Klasse definiert ist und wie Sie sie importieren? Vielen Dank! –

+0

Es ist der globale Browser [window object] (https://developer.mozilla.org/en-US/docs/Web/API/Window) als _window_ (Liebhaberfall) verfügbar. Es wird während des Bootstraps am unteren Rand injiziert. Hm ..., könnte es sein, dass der provider-name in diesem Fall eine Zeichenkette oder besser ein OpaqueToken sein muss, da typescript/angular die Eigenschaft Window name verwirren könnte? – TomKeegasi

+0

Ich vergaß zu erwähnen, das ist eine Laufzeit (Browser) Fehler nicht Kompilierzeit (TSC) ... – TomKeegasi

Antwort

5

Es ist mir unklar, was die Frage nach tatsächlich ist aber

Typen string für ein Konstruktorparameter eines injizierbaren macht keinen Sinn, ohne @Inject(...)

@Injectable() 
export class Token { 
    private token: string; 

    public constructor(token: string, window: Window) { // <<== invalid 
    this.token = window.atob(token); 
    }; 

    public getToken(): string { 
    return this.token; 
    } 
} 

sondern weil Sie verwenden es lik e

new Token(token, this.window); 

es scheint, dass nur @Injectable() sollte von dieser Klasse entfernt werden.


über die Fehlermeldung: Es sieht aus wie Window nicht richtig importiert wird, oder es ist kein Typ, sondern ein OpaqueToken oder ein string.

@Inject() ist erforderlich, wenn ein Schlüssel, der sich vom Parametertyp unterscheidet, von der Abhängigkeitsinjektion verwendet werden soll. In Ihrem Fall sieht es so aus, als ob Window kein Typ (Klasse) ist und deshalb nicht funktioniert, wenn es als solches verwendet wird.

+3

Nizza Fang, du hast Recht Ich sollte die injizierbare für die Tokenklasse fallen lassen, da der _token_ Parameter nicht beabsichtigt ist injiziert werden, aber eigentlich mehr von einem Eingabeparameter. Ihr Kommentar über das Fenster klingelt, da das Fenster _object_ vom Browser kommt, ist es wahrscheinlich nicht dekoriert (keine Metadaten) und daher benötigt eckig den Inject-Doktor auf dem Fabrikfensterparameter; Klingt richtig. – TomKeegasi