Угловой: как правильно реализовать 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();
}