2017-07-19 26 views
1

在我們的Angular應用程序中,我們需要在初始化應用程序之前從服務器加載配置設置。Angular:具有GlobalErrorHandler的APP_INITIALIZER

使用APP_INITIALIZERsuch的偉大工程:

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並想告訴角度來使用我們的GlobalErrorHandler,所以我提供的ErrorHandler,並告訴角度使用類GlobalErrorHandler。

providers: [ 
      ConfigService, 
      { 
       provide: APP_INITIALIZER, 
       useFactory: loadConfig, 
       deps: [ConfigService], 
       multi: true 
      },   
      { 
       provide: ErrorHandler, 
       useClass: GlobalErrorHandler 
      } 
    ] 

GlobalErrorHandler需要來自配置設置的信息,我需要實例化GlobalErrorHandler後,設置的承諾解決。在上面的設置中,GlobalErrorHandler是在我向服務器調用配置值之前創建的。

如何從服務器加載配置值,然後實例化GlobalErrorHandler並使用配置值?

回答

1

這似乎不可能用你想要的方式完成。 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

相關問題