在启动组件之前获取配置参数

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 有点生疏了,但我不认为仅仅因为您将 Configconfig.load() 指定为 Angular DI 框架的依赖项,它实际上会尊重它基于 Promise 的性质和延迟组件的构建,直到 Promise 被解决。


有更多 Angular 经验的人可能会发表更多评论提供解决方案。

但是,以不同于 HTTP 调用的方式向应用程序获取配置数据会更好。最有可能的是,应用程序负载如下所示:

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

您有一个额外的 HTTP 请求,这会减慢初始加载速度,并增加所有这些额外的复杂性,并且并不会真正为您 买那么多

在代码中将这些数据作为常量会更好,对于不同的环境可能使用不同的值。您不太可能经常更改它,在这种情况下,可能无论如何都会重新部署您的应用程序。根据您的服务完成方式,提供 javascript 的 Web 服务器可以将值直接烘焙到 JS 中,具体取决于它的配置。更容易控制服务器端组件的环境和配置。

【讨论】:

以上是关于在启动组件之前获取配置参数的主要内容,如果未能解决你的问题,请参考以下文章

android自定义serviceloader接口隔离及获取自定义properties参数配置

SpringBoot:springboot启动参数

常用jvm参数配置

hadoop 调优措施 调优参数

js跳转vue

springbootrun方法啥时候扫描的配置类