对于这样的事情,您应该使用应用初始化服务。应用初始化程序在您的应用程序中的所有其他内容之前运行,并且您的应用程序在完成之前不会加载。它的结构是这样的:
import { Injectable, APP_INITIALIZER } from '@angular/core';
export interface AppConfig {
api1: string;
api2: string;
}
@Injectable()
export class ConfigService {
protected config: AppConfig;
constructor(private _http: HttpClient) {
}
getConfigData(): Observable<any> {
return this._http.get<AppConfig>('... your config url...')
.catch(error => {
alert('Unable to read configuration file:' + JSON.stringify(error));
return Observable.throw(error);
});
}
public load() {
return new Promise((resolve, reject) => {
this.getConfigData()
.subscribe(
config => {
this.config= config ;
resolve(true);
},
err => resolve(err)
);
});
}
}
export function ConfigServiceInitFactory(configService: ConfigService) {
return () => configService.load();
}
export const ConfigServiceInitProvider = {
provide: APP_INITIALIZER,
useFactory: ConfigServiceInitFactory,
deps: [ConfigService],
multi: true
}
然后您将 ConfigServiceInitProvider 与 ConfigService 一起添加到您的 AppModule 提供程序(将 ConfigService 放在 ConfigServiceInitProvider 之前),然后在需要的地方注入 ConfigService 并访问配置值,例如:
constructor(private _config: ConfigService) {
this.apiBase = this._config.config.api1;
}
我不喜欢 _config.config 的重复性,所以我通常也会在我的配置服务上定义 getter,例如:
get api1() { return this.config.api1 }
然后你就可以打电话了:
this.apiBase = this._config.api1;
但是,如果您询问是否可以在 constants.ts 文件中设置值,以便可以像这样使用它:
import {Constants} from 'app/constants';
constructor() {
this.apiBase = Constants.api1;
}
在运行时从服务器加载的内容无法做到这一点,因为当您运行构建命令时,您的所有打字稿都被编译为 javascript。因此,从逻辑上讲,如果不将其作为服务值提供,您就无法使用从服务器加载的内容创建构建。您将始终需要注入服务。
解决此问题的唯一方法是在运行构建之前插入不同的常量文件,然后您就无需从服务器调用配置。但这有它自己的缺点,例如它需要完全重建和重新部署以更新配置值,这首先与配置点相悖。