Ionic2/Angular2 - прочитать пользовательский файл конфигурации

Я работаю над проектом ionic2, и мне нужно создать новый настраиваемый конфигурационный файл JSON. Я нашел несколько учебников для создания одного и доступа к нему через http.get, но мне кажется странным называть его через запрос на получение. Я хочу его в корневой папке (где все JSON-конфигурации), и я открываю/читаю файл напрямую.

Я не знаю, возможно ли это или даже рекомендовано? Вот почему я размещаю здесь свои мнения и решения:)

Спасибо

Ответ 1

Лично мне не нравится читать файл config.json, используя способ http.get для обработки информации о конфигурации, и хотя должен быть еще один способ просто включить и прочитать json файл в вашем коде, так как мы 're using Angular2 и Typescript, почему бы не использовать классы, интерфейсы и делать это более причудливо?

То, что я покажу вам, может показаться сложнее, чем сначала (хотя после прочтения вы найдете это очень простым и понятным), но когда я начал изучать Angular2, я увидел пример того, как они обрабатывали файлы конфигурации в Руководство по вводу зависимостей, и я следил за тем, что в приложениях, над которыми я работал, для обработки информации о конфигурации (например, конечных точек API, по умолчанию значения и т.д.).

Согласно документам:

Неклассовые зависимости

[...]

Приложения часто определяют объекты конфигурации с большим количеством мелких факты (например, название приложения или адрес веб-API конечная точка), но эти объекты конфигурации не всегда являются экземплярами класс.

Одно решение для выбора токена поставщика для неклассовых зависимостей заключается в определении и использовании OpaqueToken

Таким образом, вам нужно будет определить объект конфигурации с URL-адресами и т.д., а затем OpaqueToken, чтобы иметь возможность использовать его при инжекции объекта с вашей конфигурацией.

Я включил всю свою конфигурацию в файл app-config.ts

// Although the ApplicationConfig interface plays no role in dependency injection, 
// it supports typing of the configuration object within the class.
export interface ApplicationConfig {
  appName: string;
  apiEndpoint: string;
}

// Configuration values for our app
export const MY_CONFIG: ApplicationConfig = {
  appName: 'My new App',
  apiEndpoint: 'http://www...'
};

// Create a config token to avoid naming conflicts
export const MY_CONFIG_TOKEN = new OpaqueToken('config');

Вначале может возникнуть путаница OpaqueToken, но это просто строка, которая позволит избежать конфликтов имен при инъекции этого объекта. Вы можете найти удивительную статью об этом здесь.

Затем вам просто нужно включить его на нужную вам страницу следующим образом:

import { NavController } from 'ionic-angular/index';
import { Component, OpaqueToken, Injectable, Inject } from "@angular/core";

// Import the config-related things
import { MY_CONFIG_TOKEN, MY_CONFIG, ApplicationConfig } from 'app-config.ts';

@Component({
  templateUrl:"home.html",
  providers: [{ provide: MY_CONFIG_TOKEN, useValue: MY_CONFIG }]
})
export class HomePage {

  private appName: string;
  private endPoint: string;

  constructor(@Inject(MY_CONFIG_TOKEN) private config: ApplicationConfig) {
    this.appName = config.appName;
    this.endPoint = config.apiEndpoint;
  }
}

Обратите внимание, как включить его в массив providers

providers: [{ provide: MY_CONFIG_TOKEN, useValue: MY_CONFIG }]

И как сообщить инжектору, как он должен получить экземпляр объекта конфигурации

@Inject(MY_CONFIG_TOKEN) config: ApplicationConfig

UPDATE

OpaqueToken устарел с версии 4.0, поскольку он не поддерживает информацию о типе, вместо этого используйте InjectionToken<?>.

Итак, вместо этих строк:

import { OpaqueToken } from '@angular/core';

// Create a config token to avoid naming conflicts
export const MY_CONFIG_TOKEN = new OpaqueToken('config');

Теперь мы должны использовать

import { InjectionToken } from '@angular/core';

// Create a config token to avoid naming conflicts
export const MY_CONFIG_TOKEN = new InjectionToken<ApplicationConfig>('config');

Ответ 2

После чтения и чтения различных решений я закончил использование этой взломанной реализации. Надеюсь, скоро будет хорошее и родное решение:

import { NgModule } from '@angular/core';
import { environment as devVariables } from './environment.dev';
import { environment as testVariables } from './environment.test';
import { environment as prodVariables } from './environment.prod';

export function environmentFactory() {
  const location = window.location.host;
  switch (location) {
    case 'www.example.org': {
      return prodVariables;
    }
    case 'test.example.org': {
      return testVariables;
    }
    default: {
      return devVariables;
    }
  }
}

@NgModule({
  providers: [
    {
      provide: 'configuration',
      useFactory: environmentFactory
    }
  ]
})
export class EnvironmentsModule {}

а затем, когда это необходимо, например:

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

import { AuthenticationService } from '../authentication';

@Injectable()
export class APIService {

  private http: Http;
  private apiURL: string;
  protected authentication: AuthenticationService;

  constructor(
    public injector: Injector,
    @Inject('configuration') public configuration: any
  ) {
    this.http = injector.get(Http);
    this.authentication = injector.get(AuthenticationService);
    this.apiURL = configuration.apiURL;    
  };

...