2016-09-09 6 views
10

Przed RC5 używałem appref wtryskiwacz jako lokalizator usług takich jak to:Zapisywanie instancji wtryskiwacza do stosowania w elementach

Startup.ts

bootstrap(...) 
.then((appRef: any) => { 
    ServiceLocator.injector = appRef.injector; 
}); 

ServiceLocator.ts

export class ServiceLocator { 
    static injector: Injector; 
} 

składniki:

let myServiceInstance = <MyService>ServiceLocator.injector.get(MyService) 

Nie w robi to samo w bootstrapModule(). then() nie działa, ponieważ wydaje się, że komponenty zaczynają działać przed obietnicą.

Czy istnieje sposób na zapisanie instancji wtryskiwacza przed załadowaniem komponentów?

Nie chcę używać wtrysku konstruktora, ponieważ używam wtryskiwacza w komponencie bazowym, który pochodzi z wielu komponentów i raczej nie wstrzykiwam wtryskiwacza do wszystkich z nich.

Odpowiedz

8

Udało mi się to zrobić, korzystając z ręcznego wspomagania. Nie używaj "bootstrap: [AppComponent]" deklarację w @NgModule użyć ngDoBootstrap metody Zamiast:

export class AppModule { 
    constructor(private injector: Injector) { 
    } 

    ngDoBootstrap(applicationRef: ApplicationRef) { 
     ServiceLocator.injector = this.injector; 
     applicationRef.bootstrap(AppComponent); 
    } 
} 
+1

dlaczego nie zrobić assigment w konstruktorze AppModule odchodzi 'bootstrap: [AppComponent]' i nie używać 'ngDoBootstrap'? Czy istnieje szansa, że ​​konstruktor AppModule może zostać wywołany po bootstrowaniu? –

+0

@PetrMarek: Nie pamiętam tego całkiem dobrze, ale myślę, że dostajesz tylko ApplicationRef w zdarzeniu ngDoBootstrap. – dstr

+3

Przechowuję referencję Injector w konstruktorze AppModule i wygląda na to, że działa dobrze. (nie używaj ngDoBootstrap) –

2

Innym rozwiązaniem z kanciasty 2.0.0 final:

platformBrowserDynamic().bootstrapModule(AppModule, [ 
    { 
    defaultEncapsulation: ViewEncapsulation.Emulated, 
    providers: [ 
     { provide: TRANSLATIONS, useValue: TRANSLATION }, 
     { provide: TRANSLATIONS_FORMAT, useValue: 'xlf' }, 
     { provide: LOCALE_ID, useValue: 'fr' } 
    ] 
    } 
]).then((modref: NgModuleRef<any>) => { 
    appInjector(modref.injector); 
}); 
+0

Czy na pewno to działa? Ponieważ komponenty wykonywane podczas ładowania początkowego i wtryskiwacza działają po komponentach, zostawiając mnie z pustą usługą ServiceLocator.instance? – dstr

+0

@dstr, używam tego kodu na mojej aplikacji i to działa. Którą z wersji kątowych używasz? Czy możesz pominąć kopię śledzenia stosu błędów? (Przepraszam za mój zły angielski!) – jarjar

11

Na dzisiejszym maszynopis i kątowe 5, unikając WARNING in Circular dependency detected podczas importowania globalny wtryskiwacz, najpierw zadeklaruj pomocnika, np app-injector.ts:

import {Injector} from '@angular/core'; 

/** 
* Allows for retrieving singletons using `AppInjector.get(MyService)` (whereas 
* `ReflectiveInjector.resolveAndCreate(MyService)` would create a new instance 
* of the service). 
*/ 
export let AppInjector: Injector; 

/** 
* Helper to set the exported {@link AppInjector}, needed as ES6 modules export 
* immutable bindings (see http://2ality.com/2015/07/es6-module-exports.html) for 
* which trying to make changes after using `import {AppInjector}` would throw: 
* "TS2539: Cannot assign to 'AppInjector' because it is not a variable". 
*/ 
export function setAppInjector(injector: Injector) { 
    if (AppInjector) { 
     // Should not happen 
     console.error('Programming error: AppInjector was already set'); 
    } 
    else { 
     AppInjector = injector; 
    } 
} 

Następnie w AppModule, ustaw ją za pomocą:

import {Injector} from '@angular/core'; 
import {setAppInjector} from './app-injector'; 

export class AppModule { 
    constructor(injector: Injector) { 
     setAppInjector(injector); 
    } 
} 

i gdziekolwiek potrzebne, przeznaczenie:

import {AppInjector} from './app-injector'; 
const myService = AppInjector.get(MyService); 
+0

Gdyby ten jeden początkowo 'var injector = ReflectiveInjector.resolveAndCreate ([AppService); var appAlertService = injector.get (AppService); 'który nie zadziałał jak moje' AppService' miał 'ngrx Store' wstrzyknięty i rzucał' no Store provider found', więc z 'AppInjector.get (AppService);' wszystko działało w porządku. Jakieś pomysły, dlaczego? – Kuncevic

+1

@Kuncevic, nie wiem. Ale dla pewności: twoja pierwotna wersja tworzy nową instancję 'AppService', nie jest udostępniana innym komponentom, które mogą jej używać (podczas gdy powyższe rozwiązanie ma jeden wspólny singleton). Wciąż oczekiwałbym, że twoja nowo utworzona instancja zostanie poprawnie wstrzyknięta przez wszystkie współdzielone zależności, których potrzebuje, ale najwyraźniej nie. – Arjan

+0

To jest po prostu świetne.Rozwiązałem wszystkie moje problemy –