在启动组件之前获取configuration参数

我有一个问题,在我的应用程序组件开始之前,从一个JSON文件中获取configuration参数。 对于这些组件,我需要configuration参数。

没有错误消息,但app.component.ts不启动。 执行停止的地方。 阅读json工作正常。

functiontest.dev.config.json

{ "name": "DE164813", "node-uri": "http://localhost:4000" } 

Config.ts

 import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import { Http, Response } from '@angular/http'; @Injectable() export class Config { private _env: Object constructor(private http: Http) { } load() { return new Promise((resolve, reject) => { this.http.get('functiontest.dev.config.json') .map(res => res.json()) .subscribe((env_data) => { this._env = env_data; console.log("got env", this._env); }) }); } getEnv(key: any) { return this._env[key]; } }; 

app.module.ts

 import { BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; import { HttpModule } from '@angular/http'; import { DatePickerModule } from 'ng2-datepicker'; import { Config } from './service/Config'; import { APP_INITIALIZER } from '@angular/core'; import { NgModule, ApplicationRef } from '@angular/core'; import { removeNgStyles, createNewHosts, createInputTransfer } from '@angularclass/hmr'; import { RouterModule, PreloadAllModules } from '@angular/router'; /* * Platform and Environment providers/directives/pipes */ import { ENV_PROVIDERS } from './environment'; import { ROUTES } from './app.routes'; // App is our top level component import { AppComponent } from './app.component'; import { APP_RESOLVER_PROVIDERS } from './app.resolver'; import { AppState, InternalStateType } from './app.service'; import { HomeComponent } from './home'; import { AboutComponent } from './about'; import { SensorTestComponent } from './sensortest'; import { TestReviewComponent } from './testreview'; import { NoContentComponent } from './no-content'; import { XLargeDirective } from './home/x-large'; import { ContractSelectComponent } from './contractselect/contractselect.component'; // Application wide providers const APP_PROVIDERS = [ ...APP_RESOLVER_PROVIDERS, AppState ]; type StoreType = { state: InternalStateType, restoreInputValues: () => void, disposeOldHosts: () => void }; function initConfig(config: Config){ return () => config.load() } /** * `AppModule` is the main entry point into Angular2's bootstraping process */ @NgModule({ bootstrap: [ AppComponent ], declarations: [ AppComponent, AboutComponent, HomeComponent, NoContentComponent, XLargeDirective, ContractSelectComponent, SensorTestComponent, TestReviewComponent ], imports: [ // import Angular's modules BrowserModule, FormsModule, HttpModule, DatePickerModule, RouterModule.forRoot(ROUTES, { useHash: true, preloadingStrategy: PreloadAllModules }) ], providers: [ // expose our Services and Providers into Angular's dependency injection ENV_PROVIDERS, APP_PROVIDERS, Config, { provide: APP_INITIALIZER, useFactory: initConfig, deps: [Config], multi: true } ] }) export class AppModule { constructor( public appRef: ApplicationRef, public appState: AppState ) { } public hmrOnInit(store: StoreType) { if (!store || !store.state) { return; } console.log('HMR store', JSON.stringify(store, null, 2)); // set state this.appState._state = store.state; // set input values if ('restoreInputValues' in store) { let restoreInputValues = store.restoreInputValues; setTimeout(restoreInputValues); } this.appRef.tick(); delete store.state; delete store.restoreInputValues; } public hmrOnDestroy(store: StoreType) { const cmpLocation = this.appRef.components.map((cmp) => cmp.location.nativeElement); // save state const state = this.appState._state; store.state = state; // recreate root elements store.disposeOldHosts = createNewHosts(cmpLocation); // save input values store.restoreInputValues = createInputTransfer(); // remove styles removeNgStyles(); } public hmrAfterDestroy(store: StoreType) { // display new elements store.disposeOldHosts(); delete store.disposeOldHosts; } } 

app.routes.ts

 import { Routes, RouterModule } from '@angular/router'; import { HomeComponent } from './home'; import { ContractSelectComponent } from './contractselect/contractselect.component'; import { SensorTestComponent } from './sensortest'; import { TestReviewComponent } from './testreview'; import { AboutComponent } from './about'; import { NoContentComponent } from './no-content'; import { DataResolver } from './app.resolver'; export const ROUTES: Routes = [ { path: '', component: ContractSelectComponent }, { path: 'sensortest/:orderId', component: SensorTestComponent }, { path: 'testreview', component: TestReviewComponent }, { path: '**', component: NoContentComponent }, ]; 

contractselect.component.ts

 import { Component } from '@angular/core'; import { OrderResource } from '../service/OrderResource'; import { ContractSelect } from './contractselect'; import { Order } from '../model/Order'; import { Router } from '@angular/router'; import { NodeResource } from '../service/NodeResource' import { NodeData } from '../model/NodeData'; @Component({ selector: 'contractselect', providers: [OrderResource, NodeResource], templateUrl: 'contractselect.component.html' }) export class ContractSelectComponent { //... constructor(private _orderResource: OrderResource, private _router:Router, private _nodeResource: NodeResource) { this.orders = new Array<Order>(); this.orderResource = _orderResource; this.nodeResource = _nodeResource; // set delay settings this.delay = 1; console.log("created ContractSelect Component"); } // ... } 

我的Angular有点生疏,但我不认为只是因为你已经指定Configconfig.load()作为Angular DI框架的依赖,它实际上会尊重它的基于Promise的特性,组件直到Promise解决。


有更多的Angular经验的人可以评论更多, 提供一个解决scheme。

但是,如果以不同于HTTP调用的应用程序的方式获取configuration数据,那么最好使用它。 很可能,应用程序负载看起来像这样:

  • 客户端浏览器向您的服务器发出HTTP请求,并获取一个网页+一大堆JS,代表单页面Angular应用程序。
  • 单页面应用程序然后向服务器发出另一个HTTP请求以获取configuration。
  • 应用程序根据configuration进行初始化。

你有一个额外的HTTP请求,这减慢了初始负载,并增加了所有这些额外的复杂性,并没有真正买你那么多。

将数据作为代码中的常量,可能会为不同的环境提供不同的值。 你不太可能经常改变它,在这种情况下,重新部署你的应用程序可能会被完成。 取决于你的服务是如何完成的,服务于JavaScript的Web服务器可以将值直接烧入JS,这取决于它的configuration。 控制服务器端组件的环境和configuration要容易得多。