服务

时间:2018-01-19 17:30:16

标签: angular

我正在使用angular 5和httpclient。我不是内置环境的忠实粉丝来设置我需要消耗的环境api url。我已经切换到使用nginx.conf,我在其中进行api调用,返回一个json,其中包含从环境变量设置的api url。

我有一个服务,我正在进行http.get调用以获取json配置文件。

@Injectable()
export class ConfigurationService {
private baseUrl = 'https://someUrl.com';

constructor( private http: HttpClient ) {

}

getConfig(): Observable<any> { 
  return this.http
  .get(this.baseUrl + '/config')
  .map(res=>res);   
};
}

当应用程序首次启动时,将从我的app.component.ts调用此服务。

我有一个constants.ts文件,我想用它来引用我的api urls

export class Constants {    

public api1 = //NEED API1 URL FROM SERVICE HERE;
public api2= //NEED API2 URL FROM SERVICE HERE;

从服务中引入数据的最佳方法是什么?我的常量文件不仅仅是一个类的组件。

3 个答案:

答案 0 :(得分:0)

您应该将constant作为@Injectable的类,并设置方法将值设置如下

@Injectable()
export class Constants {    

   api1 :string; // NEED API1 URL FROM SERVICE HERE;

   api2: string; // NEED API2 URL FROM SERVICE HERE


   setValueApi1(val){
       this.api1 = val;
   }
}

您可以将此注入构造函数并调用方法以通过传递响应来设置值,如下所示

@Injectable()
export class ConfigurationService {
private baseUrl = 'https://someUrl.com';

constructor( private http: HttpClient,private constants:Constants ) {  }

    getConfig(): Observable<any> { 
      return this.http
      .get(this.baseUrl + '/config')
      .map(res=>res)
    }
}

在您的组件中,您可以订阅响应值并通过调用以下方法设置api值

this.getConfig().subscribe(response => {
    this.constants.setValueApi1(response))
})

答案 1 :(得分:0)

对于类似的内容,您应该使用应用初始化服务。应用初始化程序会在应用程序中的所有其他内容之前运行,并且在完成之前,您的应用程序将无法加载。它的结构如下:

import { Injectable, APP_INITIALIZER } from '@angular/core';

export interface AppConfig {
    api1: string;
    api2: string;
}

@Injectable()
export class ConfigService {
  protected config: AppConfig;

  constructor(private _http: HttpClient) {
  }

  getConfigData(): Observable<any> {
    return this._http.get<AppConfig>('... your config url...')
      .catch(error => {
        alert('Unable to read configuration file:' + JSON.stringify(error));
        return Observable.throw(error);
      });
  }

  public load() {
     return new Promise((resolve, reject) => {
       this.getConfigData()
         .subscribe(
           config => {
             this.config= config ;
             resolve(true);
           },
           err => resolve(err)
         );
     });
  }
}

export function ConfigServiceInitFactory(configService: ConfigService) {
  return () => configService.load();
}

export const ConfigServiceInitProvider = {
  provide: APP_INITIALIZER,
  useFactory: ConfigServiceInitFactory,
  deps: [ConfigService],
  multi: true
}

然后将ConfigServiceInitProvider与ConfigService一起添加到AppModule提供程序(在ConfigServiceInitProvider之前放置ConfigService),只需在需要的地方注入ConfigService并访问配置值,如:

constructor(private _config: ConfigService) {
    this.apiBase = this._config.config.api1;
}

我不喜欢_config.config的重复性,所以我通常也会在我的配置服务上定义getters,如:

get api1() { return this.config.api1 }

然后你可以打电话:

this.apiBase = this._config.api1;

但是,如果你问是否可以在constants.ts文件中设置值,以便它可以像:

一样使用
import {Constants} from 'app/constants';

constructor() {
   this.apiBase = Constants.api1;
}

在运行时从服务器加载的内容无法完成,因为在运行构建命令时,所有的typescript都会编译为javascript。因此,您逻辑上无法使用从服务器加载的内容创建构建,而不将其作为服务值提供。您将始终必须注入服务。

解决这个问题的唯一方法是在运行构建之前插入不同的常量文件,然后您永远不需要从服务器调用配置。但这有它本身的缺点,例如它需要完全重建和重新部署以更新配置值,这首先是一种配置点。

答案 2 :(得分:0)

一种简单的方法就是这样:

class Constants {
    public api1: string;
    public api2: string;

    public setApi1(api: string) {}
    public setApi2(api: string) {}
}

export const CONSTANTS: Constants = {
    api1: "DEFAULT API 1",
    api2: "DEFAULT API 2",
    setApi1(api: string) : void {
        this.api1 = api;
    },
    setApi2(api: string) : void {
        this.api2 = api;
    }
}

然后只需在需要持久性的地方导入const

import {CONSTANTS} from "../path/to/constant.ts";