APP_INITIALIZER 不阻止导入的模块

pjl*_*b12 6 angular

我有一个 Angular (v6.0.0) 应用程序,我试图在APP_INITIALIZER. 我已经阅读了几篇文章(例如thisthisthis)以及诸如this之类的SO问题,并且大多数情况下都可以正常工作。

我让应用程序调用配置服务函数来在应用程序引导时(在 期间APP_INITIALIZER)加载配置。这一切都完美无缺。问题是应用程序的其他部分正在加载/初始化/在配置加载之前调用它们的构造函数,因此无法使用文件中的配置。以下是 app.module 文件的摘录:

function initConfig(configService: AppConfigService) {
    return () => configService.loadConfig();
}

...

@NgModule({
    imports: [AuthModule, SharedModule]
    providers: [
        {
            provide: APP_INITIALIZER,
            useFactory: initConfig,
            deps: [AppConfigService],
            multi: true
        },
        ...
    ]
})
Run Code Online (Sandbox Code Playgroud)

和 AppConfigService 文件:

public loadConfig() {
    return this._http.get('./assets/app-config/config.json')
        .toPromise()
        .then((config: any) => {
            this.config = config;
        })
}
Run Code Online (Sandbox Code Playgroud)

如您所见,该loadConfig函数返回一个承诺,并加载配置(我已经确认)。

但是,我尝试访问 AuthModule 构造函数中的配置(因此我可以提取与服务器进行身份验证所需的配置值)和 SharedModule 中的服务(在这种情况下它正在寻找 Sentry DSN),并且它们两者都在加载配置之前运行。我敢肯定还会有其他例子,但这是我目前发现的。

我的印象是应用程序中的任何内容在APP_INITIALIZER解决之前都不会加载,但显然情况并非如此。我缺少什么来完成这个吗?我可以做些什么来使所有其他模块在初始化之前等待配置加载?如果没有,它基本上违背了运行时配置的目的。

小智 -1

我最近遇到了您所面临的问题。不幸的是,正如您可能已经知道的那样,APP_INITIALIZER 不会阻止模块的导入。您可以使用全局窗口对象来附加您的配置数据。这样,就可以在您的应用程序中全局访问数据。

public loadConfig() {
    return this._http.get('./assets/app-config/config.json')
        .toPromise()
        .then((config: any) => {
            window['appConfigData'] = config;
            this.config = config;
        })
}
Run Code Online (Sandbox Code Playgroud)

在属于 SharedModule 的服务中,您可以简单地从窗口对象访问配置数据。

constructor() {
  ..
  ..
    const configData = window['appConfigData'];
}
Run Code Online (Sandbox Code Playgroud)