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

标签 json node.js angular asynchronous configuration-files

我在应用程序组件启动之前从 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");
    }

// ...
}

最佳答案

我的 Angular 有点生疏,但我不认为这只是因为您指定了 Configconfig.load() 作为对Angular DI 框架,它实际上会尊重其基于 Promise 的性质,并延迟组件的构建,直到 Promise 得到解决。

<小时/>

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

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

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

您有一个额外的 HTTP 请求,这会减慢初始加载速度,并增加所有这些额外的复杂性,但实际上并没有给您带来那么多。

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

关于json - 启动组件之前获取配置参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42273678/

相关文章:

c# - 在 View 中显示来自 Controller 的 json 数据

php - 使用 JSON,将变量从 php 传递到 javascript

php - 如何在nodejs中使用https连接?

node.js - 解析服务器和 mongodb 问题

angular - Cypress:如何正确关闭 mat-select

php - 发出警告 : json_decode() expects at most 2 parameters, 4

regex - 如何将 Unicode 字母与 JSON 模式模式(正则表达式)匹配

JavaScript 在带有回调的循环中异步

javascript - 类型 'navigate' 上不存在属性 'Router' 。你的意思是 'navigated' 吗?

javascript - Angular 2 http Observable 请求不返回响应 header