2016-09-09 7 views
10

Перед RC5 я использовал appref форсунку в качестве службы локатора, как это:Хранение экземпляра инжектора для использования в компонентах

Startup.ts

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

ServiceLocator.ts

export class ServiceLocator { 
    static injector: Injector; 
} 

компоненты:

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

Нет w делает то же самое в bootstrapModule(). then() не работает, потому что компоненты, похоже, начинают выполнять перед обещанием.

Есть ли способ хранения экземпляра инжектора перед загрузкой компонентов?

Я не хочу использовать инъекцию конструктора, потому что я использую инжектор в базовом компоненте, который был получен многими компонентами, и я скорее не буду вводить инжектор им всем.

ответ

8

Мне удалось это сделать, используя ручную форматирование. Не используйте "bootstrap: [AppComponent]" заявление в @NgModule, используйте метод ngDoBootstrap вместо:

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

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

почему бы не сделать распайка в конструкторе AppModule Опережая 'bootstrap: [AppComponent]' и не использовать 'ngDoBootstrap'? Или есть вероятность, что конструктор AppModule может быть вызван после bootstraping? –

+0

@PetrMarek: Я не очень хорошо это помню, но я думаю, что вы получите ApplicationRef только в событии ngDoBootstrap. – dstr

+3

Я сохраняю ссылку Индекса в конструкторе AppModule и, похоже, работает нормально. (не используйте ngDoBootstrap) –

2

Другого решение с угловой 2.0.0 окончательные:

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

Вы уверены, что это сработало? Поскольку компоненты выполняются во время загрузки и работы инжектора после компонентов, оставляя меня с нулевым значением ServiceLocator.instance? – dstr

+0

@dstr, я использую этот код в своем приложении, и он работает. Какую угловую версию вы используете? Можете ли вы пройти копию трассировки стека ошибок? (Извините за мой плохой английский!) – jarjar

11

Для сегодняшней машинописи и Угловые 5, избегая WARNING in Circular dependency detected при импорте глобальный инжектор, сначала объявите помощника, например 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; 
    } 
} 

Далее в вашем AppModule, установите его с помощью:

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

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

И везде, где это необходимо, используйте:

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

Если бы это было изначально 'var injector = ReflectiveInjector.resolveAndCreate ([AppService); var appAlertService = injector.get (AppService); 'это не сработало, поскольку в моем« AppService »был введен« ngrx Store »и выбрано' no Store provider found', поэтому с 'AppInjector.get (AppService);' все работает просто хорошо. Любые идеи почему? – Kuncevic

+1

@ Кунцевич, я не знаю. Но просто для того, чтобы убедиться: ваша оригинальная версия создает новый экземпляр «AppService», который не используется совместно с другими компонентами, которые могут его использовать (тогда как вышеприведенное решение получает один общий синглтон). Я бы по-прежнему ожидал, что ваш вновь созданный экземпляр будет правильно введен с любыми доступными ему зависимыми зависимостями, но, по-видимому, нет. – Arjan

+0

Это просто здорово.Решил все мои проблемы –

Смежные вопросы