在启动组件之前获取配置参数
Posted
技术标签:
【中文标题】在启动组件之前获取配置参数【英文标题】:Get Config Parameters before starting components 【发布时间】:2017-07-05 13:09:26 【问题描述】:在我的应用程序组件启动之前从 json 文件中获取配置参数时遇到问题。对于这些组件,我需要配置参数。
没有错误信息,但是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");
// ...
【问题讨论】:
您可以使用 canactivate 初始化服务,并使用 get 参数 【参考方案1】:我的 Angular 有点生疏了,但我不认为仅仅因为您将 Config
和 config.load()
指定为 Angular DI 框架的依赖项,它实际上会尊重它基于 Promise 的性质和延迟组件的构建,直到 Promise 被解决。
有更多 Angular 经验的人可能会发表更多评论并提供解决方案。
但是,以不同于 HTTP 调用的方式向应用程序获取配置数据会更好。最有可能的是,应用程序负载如下所示:
客户端浏览器向您的服务器发出 HTTP 请求,并获取一个网页 + 一大包 JS,代表单页 Angular 应用程序。 然后单页应用向服务器发出另一个 HTTP 请求以获取配置。 根据配置初始化应用程序。您有一个额外的 HTTP 请求,这会减慢初始加载速度,并增加所有这些额外的复杂性,并且并不会真正为您 买那么多。
在代码中将这些数据作为常量会更好,对于不同的环境可能使用不同的值。您不太可能经常更改它,在这种情况下,可能无论如何都会重新部署您的应用程序。根据您的服务完成方式,提供 javascript 的 Web 服务器可以将值直接烘焙到 JS 中,具体取决于它的配置。更容易控制服务器端组件的环境和配置。
【讨论】:
以上是关于在启动组件之前获取配置参数的主要内容,如果未能解决你的问题,请参考以下文章