角度-在模块定义中使用动态变量

时间:2019-01-15 16:09:41

标签: angular

我有一个模块(带有@NgModule),我需要导入一个模块:

MqttModule.forRoot(environment.MQTT_SERVICE_OPTIONS)

问题是我想从环境而不是从配置文件中获取值。

我已经创建了一个从配置文件加载属性的服务,但是我不知道如何在模块定义类中使用它。 我在某些组件中使用它,并且一切工作正常(只是通过构造函数注入),但是在这里我没有上下文。

1 个答案:

答案 0 :(得分:1)

  

我已经创建了一个从配置文件中加载属性的服务,但是我不知道如何在模块定义类中使用它。

您不能使用Angular服务,因为这需要初始化注射器。在启动Angular中的任何东西之前,需要先配置 ngModule

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秒钟。

这是为什么您不应该在应用启动时异步加载资源的一个很好的理由,但是,如果您真的想这样做,就没有理由不起作用。

您需要更改promise,以便将其解析为所需的配置设置,然后将其传递给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应用程序的引导状态