gpt4 book ai didi

Angular:带有 GlobalErrorHandler 的 APP_INITIALIZER

转载 作者:行者123 更新时间:2023-12-04 00:34:52 27 4
gpt4 key购买 nike

在我们的 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 需要来自配置设置的信息,我需要在解决设置的 promise 后实例化 GlobalErrorHandler。在上面的设置中,GlobalErrorHandler 是在我调用服务器以获取配置值之前创建的。

如何从服务器加载配置值,然后实例化 GlobalErrorHandler 并使用配置值?

最佳答案

以您希望的方式完成似乎是不可能的。 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;
});
});
});
}

如您所见,在触发回调之前,从注入(inject)器请求了 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

关于Angular:带有 GlobalErrorHandler 的 APP_INITIALIZER,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45198951/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com