在Angular 6中加载配置文件

时间:2018-06-07 19:44:42

标签: angular angular6

我试图了解如何在Angular 6中加载配置文件,我目前有一个带有以下代码的ConfigureService来加载文件:

configUrl = '../assets/config.json';
config: Config;

load() {
  console.log('loading configuration');
  this.getConfig().subscribe(
    (data: Config) => {
      console.log('Config request success');
      (this.config = data);
      console.log(this.config)
    }
  );
}

private getConfig() {
  return this.http.get<Config>(this.configUrl);
}

在ConfigureService的构造函数中调用load

我使用此服务为我的api使用者服务获取我的Url字符串,并且它确实成功运行(在开发窗口中显示console.logs),但这些服务没有及时使用他们的respctive url字符串OnInit方法和其他服务在尝试从未定义的配置对象中提取字符串时会抛出错误。

我试图通过在app.module中指定它们并在启动前加载它们来读取它们,如下所示:

https://gist.github.com/fernandohu/122e88c3bcd210bbe41c608c36306db9

然而,当我尝试该方法时,它告诉我在服务器上找不到文件,并且控制台中的错误返回404,即使指定的路径是正确的。

如何确保配置服务首先运行,以便其他依赖它的服务在完成初始化之前不会尝试检索数据?

3 个答案:

答案 0 :(得分:0)

您可能要使用async / await或转发承诺:


    config: Promise<Config>;

    load() {
      console.log('loading configuration');
      this.config = requestConfig();
    }

    private requestConfig(): Promise<Config> {
       return this.http.get<Config>(this.configUrl).toPromise();
    }

    // do something asynchronously based on the config
    public async doAsynchonously(consumer: (Config => void)){
      const config = await this.config;
      consumer(config);
    }

    // return another promise that someone can react on, or use asynchronously
    // i.e. push handling of asynchronous behavior to the user of the API
    public someSettingFromConfig(): Promise<string> {
       return this.config.then(config => config.somesetting);       
    }

另请参阅:http://www.damirscorner.com/blog/posts/20170127-Angular2TutorialWithAsyncAndAwait.html
并且:https://labs.encoded.io/2016/12/08/asyncawait-with-angular/

您可能想做的另一件事是发出同步请求,我在这里发出警告:“同步请求通常对性能不利!”。

    config : Config;

    load() {
      this.config = requestConfig();
    }

    private requestConfig(): Config {
      const request= new XMLHttpRequest();
      request.open('GET', '/assets/config.json', false);
      if (request.overrideMimeType) {
        request.overrideMimeType('application/json');
      }
      request.send();
      if (request.status === 200) {
        return <Config>JSON.parse(config.responseText);
      }
      // log some error
      return undefined;
    }

答案 1 :(得分:0)

这是一个很好的问题,我们也有不同的服务器(开发,质量控制,阶段,产品), 因此,为每种环境创建单独的版本非常耗时, 我从未尝试过为每种环境创建单独的环境文件的方法, 我们通过将Api Urls和常量存储在json文件中解决了这个问题。

因此,首先创建一个json文件并将其放在 assets 文件夹中。

Config.json

{
    "url":{
    "apiUrl": "http://localhost:58357/"
    }
}

创建一个模型类,该模型类应具有与 Config.json 文件

相同名称的属性。

Config.ts

 export class Config {
    url: {
        apiUrl: string;
    };
}

创建服务以导入 Config.json 文件

app.config.service.ts

import { Injectable } from '@angular/core';
import { Config } from './models/config';
import { HttpClient, HttpBackend, HttpResponse } from '@angular/common/http';
import { Observable } from '../node_modules/rxjs';
import { map } from 'rxjs/operators';

@Injectable({
providedIn: 'root'
})
export class AppConfig {

static Settings: Config;
private http: HttpClient;
constructor(private httpBackEnd: HttpBackend) {
    this.http = new HttpClient(httpBackEnd);
}
load() {
    const jsonFile = 'assets/config.json';
    return new Promise<void>((resolve, reject) => {
    this.http.get(jsonFile).toPromise().then((response: Config) => {
       AppConfig.Settings = <Config>response;
       resolve();
    }).catch((response: any) => {
       reject(`Could not load file '${jsonFile}': ${JSON.stringify(response)}`);
    });
    });
 }
}

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule, APP_INITIALIZER } from '@angular/core';
import { AppComponent } from './app.component';
import { AppConfig } from '../app.config.service';
import { HttpClientModule } from '../../node_modules/@angular/common/http';


export function initConfig(appConfig: AppConfig) {
return () => appConfig.load();
}

@NgModule({
declarations: [
AppComponent
],
  imports: [
  BrowserModule,
  HttpClientModule,
  ],
providers: [
 AppConfig, { provide: APP_INITIALIZER, useFactory: initConfig, deps: [AppConfig], multi: true },
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

在要使用json文件中存储的密钥的任何组件文件中导入AppConfig。

app.component.ts

import { Component } from '@angular/core';
import { AppConfig } from '../app.config.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
 })
 export class AppComponent {
 title = 'ConstantsManagerDemo';
 constructor() {
 const apiUrl = AppConfig.Settings.url.apiUrl;
 alert(apiUrl);
  }
 }

转到 tsconfig.json 文件并添加

"allowSyntheticDefaultImports" :true,  
under compilerOptions

答案 2 :(得分:0)

请按照以下步骤操作:

  • 导入环境
  • 定义本地环境属性
  • 读取配置属性
import {environment} from '../../environments/environment';
env = environment;
public myProperty = this.env.property path