在我们的Angular应用程序中,我们需要在初始化应用程序之前从服务器加载配置设置。
将APP_INITIALIZER
用作such效果很好:
export function loadConfig(config: ConfigService) => () => config.load()
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule,
routes,
FormsModule,
HttpModule],
providers: [
ConfigService,
{
provide: APP_INITIALIZER,
useFactory: loadConfig,
deps: [ConfigService],
multi: true
}
],
bootstrap: [AppComponent]
})
export class AppModule {
}
然后我扩展了ErrorHandler来创建一个GlobalErrorHandler并想告诉Angular使用我们的GlobalErrorHandler,所以我提供了ErrorHandler并告诉Angular使用类GlobalErrorHandler。
providers: [
ConfigService,
{
provide: APP_INITIALIZER,
useFactory: loadConfig,
deps: [ConfigService],
multi: true
},
{
provide: ErrorHandler,
useClass: GlobalErrorHandler
}
]
GlobalErrorHandler需要来自配置设置的信息,我需要在设置的承诺解决后实例化GlobalErrorHandler。在上面的设置中,在我向服务器调用配置值之前创建了GlobalErrorHandler。
如何从服务器加载配置值,然后实例化GlobalErrorHandler并使用配置值?
答案 0 :(得分:2)
以你想要它的方式似乎不可能。 Here is the relevant code实例化ErrorHandler
并调用APP_INITIALIZER
回调:
private _bootstrapModuleFactoryWithZone<M>(moduleFactory: NgModuleFactory<M>, ngZone?: NgZone):
Promise<NgModuleRef<M>> {
...
return ngZone.run(() => {
const ngZoneInjector =
ReflectiveInjector.resolveAndCreate([{provide: NgZone, useValue: ngZone}], this.injector);
const moduleRef = <InternalNgModuleRef<M>>moduleFactory.create(ngZoneInjector);
!!! ------------- here ErrorHandler is requested and instantiated ------------ !!!
const exceptionHandler: ErrorHandler = moduleRef.injector.get(ErrorHandler, null);
if (!exceptionHandler) {
throw new Error('No ErrorHandler. Is platform module (BrowserModule) included?');
}
...
return _callAndReportToErrorHandler(exceptionHandler, () => {
const initStatus: ApplicationInitStatus = moduleRef.injector.get(ApplicationInitStatus);
!!! ------------ and here your APP_INITIALIZER callbacks are executed ---------- !!!
initStatus.runInitializers();
return initStatus.donePromise.then(() => {
this._moduleDoBootstrap(moduleRef);
return moduleRef;
});
});
});
}
正如您所看到的,在触发回调之前,请求从注射器请求ErrorHanlder
。并且之前没有其他方法可以执行服务器请求。
我相信您唯一的选择是在应用程序启动之前发出请求,然后在获得响应后,将ErrorHanlder
添加到模块提供程序并引导应用程序:
// app.module.ts
export class AppModule {}
export const decoratorDescriptor = {
imports: [BrowserModule, FormsModule, ReactiveFormsModule],
declarations: [AppComponent, DebounceDirective, ExampleComponent],
providers: [],
bootstrap: [AppComponent]
};
// main.ts
const http = injector.get(Http);
http.get('assets/configs/configuration.json').subscribe((r) => {
const ErrorHandler = configureErrorHandler(r.json());
decoratorDescriptor.providers.push(ErrorHandler);
const decorated = NgModule(decoratorDescriptor)(AppModule);
platformBrowserDynamic().bootstrapModule(decorated);
});
请参阅this answer了解如何配置http
。
答案 1 :(得分:0)
认为答案可能会帮助需要它的人...
我能够通过在GlobalErrorHandler部分中将APP_INITIALIZER作为依赖项来解决此问题。这使GlobalErrorHandler实例化,直到APP_INITIALIZER可用,从而解决了我的问题。
providers: [
ConfigService,
{
provide: APP_INITIALIZER,
useFactory: loadConfig,
deps: [ConfigService],
multi: true
},
{
provide: ErrorHandler,
useClass: GlobalErrorHandler,
deps: [APP_INITIALIZER]
}
]