2016-01-03 20 views
8

Sto cercando di collegare un'app di base Angular2 che utilizza il servizio Http. (La maggior parte delle esercitazioni che ho visto fare questo con un Component consuma il servizio Http, che sembra sbagliato a meno che la filosofia di base dei controller sottili sia cambiata - ma questa è una domanda diversa)È possibile iniettare servizi in servizi solo tramite bootstrap?

Vorrei creare un servizio che utilizza il servizio Http di Angular. Ma io non riesco a capire come iniettare il servizio Http diverso da questo:

boot.ts:

import {bootstrap} from 'angular2/platform/browser'; 
import {AppComponent} from './app.component'; 
import {HTTP_PROVIDERS } from 'angular2/http'; 

bootstrap(AppComponent, [HTTP_PROVIDERS]); 

myService.ts:

import {Injectable} from 'angular2/core'; 
import {Http} from 'angular2/http'; 

@Injectable() 
export class aService{ 
    constructor(http:Http){ 
    } 
    /** do some stuff *// 
} 

Questo funziona, ma sembrare molto errato richiedere all'utente del servizio di conoscere le dipendenze del servizio ed essere obbligato a iniettarle nel processo di bootstrap. Sembra che ci dovrebbe essere un modo per consegnare direttamente un array providers a un servizio nello stesso modo in cui è possibile un componente, ma non riesco a trovarlo. Mi manca qualcosa?

+0

"A meno che la filosofia di base dei controller sottili non sia cambiata" - non è così. Per citare la [Panoramica dell'architettura] (https://angular.io/docs/ts/latest/guide/architecture.html): "Il lavoro di un componente è quello di abilitare l'esperienza utente e nient'altro: media tra la vista ... e la logica dell'applicazione ... Delega tutto ciò che non è banale ai servizi." –

+0

Grazie @MarkRajcok - questo è il modo in cui penso che dovrebbe essere fatto. La mia confusione deriva dal fatto che la documentazione mostra che i controllori fanno molto di più. (Ad esempio: https://angular.io/docs/js/latest/api/http/Http-class.html) Se si suppone che i componenti siano veramente sottili, probabilmente non si occuperanno di http molto spesso, ma i documenti implicano che è normale. –

+0

Beh, è ​​improbabile che gli esempi nei documenti API seguano le best practice per la progettazione di un'app e ciò è probabilmente ragionevole. –

risposta

3

Aggiornamento

In questo modo se un iniettore genitore fornisce un'implementazione per OtherService viene utilizzato questo, altrimenti OtherServiceImpl viene usato (default).

@Injectable() 
class SomeService { 
    OtherService _other; 

    SomeService(Injector injector) { 
    _other = injector.getOptional(OtherService); 
    if (_other == null) { 
     _other = injector.resolveAndCreateChild([ 
     provide(OtherService, useClass: OtherServiceImpl) 
     ]).get(OtherService); 
    } 
    _other.doSomething(); 
    } 
} 

Se si forniscono viene utilizzato un altro come

bootstrap(AppElement, [ 
    provide(OtherService, useClass: OtherServiceImpl2) 
]); 

OtherServiceImpl2.

Vedi anche https://github.com/angular/angular/issues/5622

originale

Si può solo rendere il servizio http opzionale (utilizzando il @Optional() annotazione) e se non viene fornito solo creare un'istanza all'interno del costruttore con new Http(). In questo modo l'utente non ha il necessario per conoscere le dipendenze dei servizi,, ma è in grado di passare implementazioni alternative se necessario (ad esempio per il test). Se la creazione del dependeny all'interno del servizio richiede DI stesso, è possibile iniettare un iniettore e utilizzarlo per ottenere le dipendenze. Vedi dipendenze anche opzionali in http://blog.thoughtram.io/angular/2015/05/18/dependency-injection-in-angular-2.html

cosa potrebbe anche funzionare (non me ancora provato) è proprio quello di creare un iniettore bambino e istruzioni al fine di saltare auto

Dal SkipSelfMetadata documentazione

class Dependency { 
    } 

    @Injectable() 
    class NeedsDependency { 
    dependency; 
    constructor(@SkipSelf() dependency:Dependency) { 
     this.dependency = dependency; 
    } 
    } 

    var parent = Injector.resolveAndCreate([Dependency]); 
    var child = parent.resolveAndCreateChild([NeedsDependency]); 
    expect(child.get(NeedsDependency).dependency instanceof Depedency).toBe(true); 

    var inj = Injector.resolveAndCreate([Dependency, NeedsDependency]); 
    expect(() => inj.get(NeedsDependency)).toThrowError(); 

Non so ancora se questo risolve ancora da "sé" se il genitore non può fornire il tipo richiesto.

+0

Pensavo che chiamare "nuovo" te stesso per creare una dipendenza sia disapprovato. –

+0

Hai ragione. Se la classe istanziata ha dipendenze, questo non funziona nemmeno. Per un esempio pienamente funzionante, è necessario creare un bambino iniettore e l'istanza acquisita da questo iniettore di bambini. Aggiornerò l'esempio –

+0

Grazie per aver letto così apertamente! –

Problemi correlati