Angular - использовать динамические переменные в определении модуля - PullRequest
0 голосов
/ 15 января 2019

У меня есть модуль (с @NgModule), и мне нужно импортировать модуль:

MqttModule.forRoot(environment.MQTT_SERVICE_OPTIONS)

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

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

1 Ответ

0 голосов
/ 15 января 2019

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

Нельзя использовать службу Angular, потому что для этого требуется инициализация инжектора. ngModule должен быть настроен до того, как что-нибудь в Angular будет запущено.

Модуль root загружается строкой кода plaformBrowserDynamic().bootstrapModule(AppModule) в файле main.ts. Здесь все в Angular начинается.

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

Я могу продемонстрировать эффект, изменив main.ts на следующее:

(function () {
    return new Promise(resolver => {
        window.setTimeout(() => resolver(), 5000);
    });
})().then(() => {
    platformBrowserDynamic().bootstrapModule(AppModule)
        .catch(err => console.log(err));
});

Вышеуказанное ничего не делает, только задерживает загрузку Angular на 5 секунд.

Это хорошая причина, по которой вам не следует загружать ресурсы асинхронно при запуске приложения, но если вы действительно хотите это сделать, нет никаких причин, по которым оно не будет работать.

Вам нужно изменить обещание, чтобы оно соответствовало нужным настройкам конфигурации, а затем передать это статической функции в AppModule.

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

(function () {
    return new Promise(resolver => {
        const exampleConfig = {
            options: 'ABC'
        };
        window.setTimeout(() => resolver(exampleConfig), 5000);
    });
})().then(config => {
    platformBrowserDynamic().bootstrapModule(AppModule.withConfig(config))
        .catch(err => console.log(err));
});

Теперь вам нужно будет создать определение модуля вручную для AppModule, но это работает точно так же, как модули реализуют методы forRoot(). Я только что переименовал его в withConfig(), чтобы он звучал лучше.

@NgModule()
export class AppModule {
    static withConfig(config: any): ModuleWithProviders {
        return {
            ngModule: AppModule,
            imports: [
                MqttModule.forRoot(config)
            ]
        };
    }
}

Я настоятельно рекомендую фоновому серверу внедрить необходимые данные конфигурации в index.html, чтобы не было необходимости в асинхронной операции. Затем вы можете ссылаться на глобальную переменную в AppModule и пропустить шаг withConfig(). Сервер должен отвечать за состояние начальной загрузки приложения Angular.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...