angular - Angular6 在模块 forRoot() 中使用获取的配置变量
问题描述
在我的应用程序中,我需要使用ng-intercom
https://github.com/CaliStyle/ng-intercom,这需要在forRoot()
方法中设置配置键。
配置键是从 API 调用加载的,在main.ts
. 从 API 中获取配置,然后设置为APP_CONFIG
in AppConfigService
,然后启动应用程序。
main.ts
const appConfigRequest = new XMLHttpRequest();
appConfigRequest.addEventListener('load', onAppConfigLoad);
appConfigRequest.open('GET', 'https://api.myjson.com/bins/lf0ns');
appConfigRequest.send();
// Callback executed when app config JSON file has been loaded.
function onAppConfigLoad() {
const config = JSON.parse(this.responseText);
initConfig(config);
}
// Sets fetched config to AppConfigService constant APP_CONFIG and calls bootstrap()
function initConfig(config) {
const injector = ReflectiveInjector.resolveAndCreate([AppConfigService]);
const configService = injector.get(AppConfigService);
configService.set(config);
bootstrap();
}
function bootstrap() {
platformBrowserDynamic().bootstrapModule(AppModule).then().catch(err => console.error(err));
}
应用配置.service.ts
import { Injectable } from '@angular/core';
export let APP_CONFIG: any = {};
@Injectable()
export class AppConfigService {
constructor() {}
public set(config) {
APP_CONFIG = Object.assign(config);
}
}
在AppModule
我导入APP_CONFIG
并使用以下配置中的forRoot()
密钥IntercomModule
:
app.module.ts
import { NgModule, InjectionToken, Inject, APP_INITIALIZER } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { APP_CONFIG } from './../shared/services/app-config.service';
import { IntercomModule } from 'ng-intercom';
@NgModule({
imports: [
BrowserModule,
FormsModule,
IntercomModule.forRoot({
appId : APP_CONFIG.intercomKey,
updateOnRouterChange: false
})
],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
配置示例:
{
"production": true,
"envName": "staging",
"apiBaseURL": "//api.staging.site.com/v1/",
"intercomKey": "qz0b98qo"
}
问题:初始化 IntercomModule 时,配置键未定义APP_CONFIG.intercomKey
,因为尚未从 API 获取配置。
初始化模块时如何确保配置可用?有任何想法吗?
我之前尝试过在方法中调用一个函数,但是在使用 AOT 编译应用程序时forRoot()
出错Function calls are not supported in decorators
另请参阅 stackblitz:https ://stackblitz.com/edit/angular6-intercom-issue
解决方案
问题是 app.module.ts 中的代码在您将其导入 main.ts 后立即执行。您必须动态导入它以实现您的目标。我更新了您在 Stackblitz 上的示例以显示解决方案。
不过,您可能需要查看 TypeScript 是如何转换动态导入的。我不确定,目前是否可以针对广泛支持的 ES 版本。另请参阅此处有关该主题的 TypeScript 文档。
如果可以在服务器上请求和缓存应用程序配置,我认为这将是一个更干净的解决方案。
推荐阅读
- unity3d - 如何使用标记使我的 AR 应用程序更加稳定?
- sql - 使用 OpenX SerDe 在 Athena 中聚合 JSON 对象自己的键值属性
- entity-framework - 使用 Entity Framework Core Fluent API,如何阻止它创建自动递增的主键?
- javascript - webauthn yubico 示例不适用于 Firefox
- python - 如何在 pandas 中打开 csv 文件,显示所有列而不是仅在一列中显示整个数据?
- python - 我正在尝试标准化我的属性,但我收到标准缩放器错误,因为 Python 找不到它
- java - 由于巨大的休眠持续时间,超过了 GC 开销限制
- ansible - Ansible 嵌套的 host_vars 文件夹
- java - 按子对象中参数的值查询dsl顺序
- android - LiveData“按引用传递”初始值