typescript - Definovať globálne konštanty


V Angular 1.x môžete definovať konštanty takto:

angular.module('mainApp.config', [])
    .constant('API_ENDPOINT', 'http://127.0.0.1:6666/api/')

Aký by bol ekvivalent v Angulari (s TypeScriptom)?

Len nechcem opakovane zadávať základnú URL API vo všetkých mojich službách.

Odpoveď č. 1

Nasledujúce zmeny fungujú pre mňa vo finálnej verzii Angular 2:

export class AppSettings {
   public static API_ENDPOINT='http://127.0.0.1:6666/api/';
}

A potom počas služby:

import {Http} from 'angular2/http';
import {Message} from '../models/message';
import {Injectable} from 'angular2/core';
import {Observable} from 'rxjs/Observable';
import {AppSettings} from '../appSettings';
import 'rxjs/add/operator/map';

@Injectable()
export class MessageService {

    constructor(private http: Http) { }

    getMessages(): Observable<Message[]> {
        return this.http.get(AppSettings.API_ENDPOINT+'/messages')
            .map(response => response.json())
            .map((messages: Object[]) => {
                return messages.map(message => this.parseData(message));
            });
    }

    private parseData(data): Message {
        return new Message(data);
    }
}

Odpoveď č. 2

Riešenie pre konfiguráciu poskytnutú samotným tímom Angular nájdete tu.

Tu je všetok relevantný kód:

1) app.config.ts

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

export let APP_CONFIG = new OpaqueToken("app.config");

export interface IAppConfig {
    apiEndpoint: string;
}

export const AppConfig: IAppConfig = {    
    apiEndpoint: "http://localhost:15422/api/"    
};

2) app.module.ts

import { APP_CONFIG, AppConfig } from './app.config';

@NgModule({
    providers: [
        { provide: APP_CONFIG, useValue: AppConfig }
    ]
})

3) tvoja.služba.ts

import { APP_CONFIG, IAppConfig } from './app.config';

@Injectable()
export class YourService {

    constructor(@Inject(APP_CONFIG) private config: IAppConfig) {
             // You can use config.apiEndpoint now
    }   
}

Teraz môžete vložiť konfiguráciu všade bez použitia názvov reťazcov a s použitím vášho rozhrania na statické kontroly.

Samozrejme, môžete rozdeľovať rozhranie a konštantu ďalej, aby ste mohli poskytovať rôzne hodnoty v produkcii a pri vývoji, napríklad.

Odpoveď č. 3

Aktualizované pre Angular 4+

Teraz môžeme jednoducho použiť súbor prostredí, ktorý Angular poskytuje ako predvolený, ak je váš projekt vytvorený cez angular-cli.

napríklad

Vo vašom priečinku prostredí vytvorte nasledujúce súbory

  • environment.prod.ts
  • environment.qa.ts
  • environment.dev.ts

a každý súbor môže obsahovať súvisiace zmeny v kóde, ako napríklad:

  • environment.prod.ts
    export const environment = {
         production: true,
         apiHost: 'https://api.somedomain.com/prod/v1/',
         CONSUMER_KEY: 'someReallyStupidTextWhichWeHumansCantRead', 
         codes: [ 'AB', 'AC', 'XYZ' ],
    };
    
  • environment.qa.ts
    export const environment = {
         production: false,
         apiHost: 'https://api.somedomain.com/qa/v1/',
         CONSUMER_KEY : 'someReallyStupidTextWhichWeHumansCantRead', 
         codes: [ 'AB', 'AC', 'XYZ' ],
    };
    
  • environment.dev.ts
    export const environment = {
         production: false,
         apiHost: 'https://api.somedomain.com/dev/v1/',
         CONSUMER_KEY : 'someReallyStupidTextWhichWeHumansCantRead', 
         codes: [ 'AB', 'AC', 'XYZ' ],
    };
    

Prípad použitia v aplikácii

Môžete importovať prostredia do ľubovoľného súboru, napríklad do služieb clientUtilServices.ts

import {environment} from '../../environments/environment';
getHostURL(): string {
    return environment.apiHost;
  }

Prípad použitia pri zostavovaní

Otvorte svoj súbor Angular CLI .angular-cli.json a vo vnútri "apps": [{...}] pridajte nasledujúci kód

 "apps":[{
        "environments": {
            "dev": "environments/environment.ts",
            "prod": "environments/environment.prod.ts",
            "qa": "environments/environment.qa.ts",
           }
         }
       ]

Ak chcete vytvoriť verziu pre produkciu, spustite ng build --env=prod, načíta konfiguráciu z environment.prod.ts, rovnakým spôsobom to môžete urobiť aj pre qa alebo dev

## Staršia odpoveď

V mojom poskytovateľovi som robil niečo podobné ako nižšie:

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

@Injectable()
export class ConstantService {

API_ENDPOINT :String;
CONSUMER_KEY : String;

constructor() {
    this.API_ENDPOINT = 'https://api.somedomain.com/v1/';
    this.CONSUMER_KEY = 'someReallyStupidTextWhichWeHumansCantRead'
  }
}

Potom mám prístup ku všetkým konštantným údajom kdekoľvek

import {Injectable} from '@angular/core';
import {Http} from '@angular/http';
import 'rxjs/add/operator/map';

import {ConstantService} from  './constant-service'; //This is my Constant Service


@Injectable()
export class ImagesService {
    constructor(public http: Http, public ConstantService: ConstantService) {
    console.log('Hello ImagesService Provider');

    }

callSomeService() {

    console.log("API_ENDPOINT: ",this.ConstantService.API_ENDPOINT);
    console.log("CONSUMER_KEY: ",this.ConstantService.CONSUMER_KEY);
    var url = this.ConstantService.API_ENDPOINT;
    return this.http.get(url)
  }
 }

Odpoveď č. 4

V Angular2 máte nasledujúcu definíciu provide, ktorá vám umožňuje nastaviť rôzne druhy závislostí:

provide(token: any, {useClass, useValue, useExisting, useFactory, deps, multi}

V porovnaní s Angular 1

app.service v Angular1 je ekvivalentom useClass v Angular2.

app.factory v Angular1 je ekvivalentné useFactory v Angular2.

app.constant a app.value boli zjednodušené na useValue s menšími obmedzeniami. T. j. už neexistuje config blok.

app.provider - V Angular 2 neexistuje žiadny ekvivalent.

Príklady

Na nastavenie s koreňovým injektorom:

bootstrap(AppComponent,[provide(API_ENDPOINT, { useValue='http://127.0.0.1:6666/api/' })]);

Alebo nastavte pomocou injektora vášho komponentu:

providers: [provide(API_ENDPOINT, { useValue: 'http://127.0.0.1:6666/api/'})]

provide je skratka pre:

var injectorValue = Injector.resolveAndCreate([
  new Provider(API_ENDPOINT, { useValue: 'http://127.0.0.1:6666/api/'})
]);

S injektorom je získanie hodnoty jednoduché:

var endpoint = injectorValue.get(API_ENDPOINT);

Odpoveď č. 5

V Angular 4 môžete použiť triedu environment na uchovanie všetkých vašich globálov.

Máte predvolene súbory environment.ts a environment.prod.ts.

Napríklad

export const environment = {
  production: false,
  apiUrl: 'http://localhost:8000/api/'
};

A potom na vašej službe:

import { environment } from '../../environments/environment';
...
environment.apiUrl;

Odpoveď č. 6

Aj keď prístup s triedou AppSettings s reťazcovou konštantou ako ApiEndpoint funguje, nie je ideálny, pretože by sme nemohli v čase jednotkového testovania vymeniť tento skutočný ApiEndpoint za iné hodnoty.

Potrebujeme byť schopní injektovať tieto API endpointy do našich služieb (myslite na injektovanie služby do inej služby). Tiež nemusíme vytvárať celú triedu pre toto, všetko, čo chceme, je injektovať reťazec do našich služieb, ktorý bude našim ApiEndpointom. Aby sme doplnili vynikajúcu odpoveď od pixelbits, tu je kompletný kód, ako sa to dá urobiť v Angular 2:

Najprv musíme Angularu povedať, ako poskytnúť inštanciu nášho ApiEndpoint, keď o ňu požiadame v našej aplikácii (môžeme to chápať ako registráciu závislosti):

bootstrap(AppComponent, [
        HTTP_PROVIDERS,
        provide('ApiEndpoint', {useValue: 'http://127.0.0.1:6666/api/'})
]);         

A potom v službe vstrčíme tento ApiEndpoint do konštruktora služby a Angular nám ho poskytne na základe našej vyššie uvedenej registrácie:

import {Http} from 'angular2/http';
import {Message} from '../models/message';
import {Injectable, Inject} from 'angular2/core';  // * We import Inject here
import {Observable} from 'rxjs/Observable';
import {AppSettings} from '../appSettings';
import 'rxjs/add/operator/map';

@Injectable()
export class MessageService {

    constructor(private http: Http, 
                @Inject('ApiEndpoint') private apiEndpoint: string) { }

    getMessages(): Observable<Message[]> {
        return this.http.get(`${this.apiEndpoint}/messages`)
            .map(response => response.json())
            .map((messages: Object[]) => {
                return messages.map(message => this.parseData(message));
            });
    } 
    // the rest of the code...
}

Odpoveď č. 7

Toto je moja nedávna skúsenosť s touto situáciou:

  • @angular/cli: 1.0.0
  • node: 6.10.2
  • @angular/core: 4.0.0

Sledoval som oficiálnu a aktualizovanú dokumentáciu tu:

https://angular.io/docs/ts/latest/guide/dependency-injection.html#!#dependency-injection-tokens

Zdá sa, že OpaqueToken je teraz zastaraný a musíme používať InjectionToken, takže tieto sú moje súbory, ktoré bežia bez problémov:

app-config.interface.ts

export interface IAppConfig {

  STORE_KEY: string;

}

app-config.constants.ts

import { InjectionToken } from "@angular/core";
import { IAppConfig } from "./app-config.interface";

export const APP_DI_CONFIG: IAppConfig = {

  STORE_KEY: 'l@_list@'

};

export let APP_CONFIG = new InjectionToken< IAppConfig >( 'app.config' );

app.module.ts

import { APP_CONFIG, APP_DI_CONFIG } from "./app-config/app-config.constants";

@NgModule( {
  declarations: [ ... ],
  imports: [ ... ],
  providers: [
    ...,
    {
      provide: APP_CONFIG,
      useValue: APP_DI_CONFIG
    }
  ],
  bootstrap: [ ... ]
} )
export class AppModule {}

my-service.service.ts

  constructor( ...,
               @Inject( APP_CONFIG ) private config: IAppConfig) {

    console.log("This is the App's Key: ", this.config.STORE_KEY);
    //> This is the App's Key:  l@_list@

  }

Výsledok je čistý a na konzole nie sú žiadne upozornenia vďaka nedávnemu komentáru Johna Papu k tejto téme:

https://github.com/angular/angular-cli/issues/2034

Kľúčom bolo implementovať rozhranie v inom súbore.

Odpoveď č. 8

Všetky riešenia sa zdajú byť komplikované. Hľadám najjednoduchšie riešenie pre tento prípad a chcem len použiť konštanty. Konštanty sú jednoduché. Je niečo, čo by hovorilo proti nasledujúcemu riešeniu?

app.const.ts

'use strict';

export const dist = '../path/to/dist/';

app.service.ts

import * as AppConst from '../app.const'; 

@Injectable()
export class AppService {

    constructor (
    ) {
        console.log('dist path', AppConst.dist );
    }

}

Odpoveď č. 9

Jednoducho použite konštantu v Typescript

export var API_ENDPOINT = 'http://127.0.0.1:6666/api/';

Môžete ho použiť v závislom injektore pomocou

bootstrap(AppComponent, [provide(API_ENDPOINT, {useValue: 'http://127.0.0.1:6666/api/'}), ...]);

Súvisiace články