Угловой: как правильно реализовать APP_INITIALIZER
У меня есть приложение Angular 5.2.0.
Я посмотрел, как реализовать APP_INITIALIZER
для загрузки информации о конфигурации перед запуском приложения.
Вот выдержка из app.module
:
providers: [
ConfigurationService,
{
provide: APP_INITIALIZER,
useFactory: (configService: ConfigurationService) =>
() => configService.loadConfigurationData(),
deps: [ConfigurationService],
multi: true
}
],
Здесь configuration.service
:
import { Injectable, Inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Configuration } from './configuration';
@Injectable()
export class ConfigurationService {
private readonly configUrlPath: string = 'Home/Configuration';
private configData: Configuration;
constructor(
private http: HttpClient,
@Inject('BASE_URL') private originUrl: string) { }
loadConfigurationData() {
this.http
.get<Configuration>('${this.originUrl}${this.configUrlPath}')
.subscribe(result => {
this.configData = {
test1ServiceUrl: result["test1ServiceUrl"],
test2ServiceUrl: result["test2ServiceUrl"]
}
});
}
get config(): Configuration {
return this.configData;
}
}
Вот пример конструктора компонента, в котором используется configData
:
export class TestComponent {
public test1ServiceUrl: string;
constructor(public configService: ConfigurationService) {
this.test1ServiceUrl = this.configService.config.test1ServiceUrl;
}
}
Он отлично работает со всеми компонентами, которые определены в <router-outlet></router-outlet>
. Но та же реализация в компоненте за пределами <router-outlet></router-outlet>
не работает.
Когда я отлаживаю соответствующий конструктор компонента, где он не работает, он говорит, что configService
- это null
.
Почему APP_INITIALIZER
выполняется до вызова конструктора компонента внутри <router-outlet></router-outlet>
, но не до конструктора компонента вне <router-outlet></router-outlet>
?
Ответы
Ответ 1
Из-за того, как APP_INTIALIZER
работает, ожидалось, что асинхронные инициализаторы возвращают обещания, но ваша реализация APP_INTIALIZER
multiprovider не делает этого, потому что функция loadConfigurationData
ничего не возвращает.
Это должно быть что-то вроде:
loadConfigurationData(): Promise<Configuration> {
return this.http.get<Configuration>('${this.originUrl}${this.configUrlPath}')
.do(result => {
this.configData = result;
})
.toPromise();
}
Ответ 2
У меня была похожая проблема. Исправление было почти таким же, на самом деле вернуть обещание.
смотрите: ngOnInit запускается до выполнения APP_INITIALIZER