typescript - Määritä globaalit vakiot
Angular 1.x:ssä voit määritellä vakioita näin:
angular.module('mainApp.config', [])
.constant('API_ENDPOINT', 'http://127.0.0.1:6666/api/')
Mikä olisi vastaava Angularissa (TypeScriptillä)?
En vain halua toistaa API:n perusosoitetta yhä uudelleen kaikissa palveluissani.
Vastaus #1
Alla olevat muutokset toimivat minulla Angular 2:n lopullisessa versiossa:
export class AppSettings {
public static API_ENDPOINT='http://127.0.0.1:6666/api/';
}
Ja sitten palveluksessa:
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);
}
}
Vastaus #2
Ratkaisu kulmaisen tiimin itse tarjoamalle kokoonpanolle löytyy täältä.
Tässä on kaikki asiaankuuluva koodi:
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) palvelusi.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
}
}
Nyt voit injektoida konfiguraation kaikkialle ilman merkkijonojen nimiä ja käyttämällä rajapintaasi staattisiin tarkistuksiin.
Voit tietenkin erottaa rajapinnan ja vakion edelleen, jotta voit toimittaa erilaisia arvoja tuotannossa ja kehityksessä, esimerkiksi.
Vastaus #3
Päivitetty Angular 4+:lle
Nyt voimme yksinkertaisesti käyttää ympäristöjen tiedostoa, jonka Angular tarjoaa oletuksena, jos projektisi on luotu Angular-CLI:n kautta.
esimerkiksi
Luo ympäristöjesi kansioon seuraavat tiedostot
environment.prod.tsenvironment.qa.tsenvironment.dev.ts
ja jokainen tiedosto voi sisältää siihen liittyviä koodimuutoksia, kuten:
environment.prod.tsexport const environment = { production: true, apiHost: 'https://api.somedomain.com/prod/v1/', CONSUMER_KEY: 'someReallyStupidTextWhichWeHumansCantRead', codes: [ 'AB', 'AC', 'XYZ' ], };environment.qa.tsexport const environment = { production: false, apiHost: 'https://api.somedomain.com/qa/v1/', CONSUMER_KEY : 'someReallyStupidTextWhichWeHumansCantRead', codes: [ 'AB', 'AC', 'XYZ' ], };environment.dev.tsexport const environment = { production: false, apiHost: 'https://api.somedomain.com/dev/v1/', CONSUMER_KEY : 'someReallyStupidTextWhichWeHumansCantRead', codes: [ 'AB', 'AC', 'XYZ' ], };
Sovelluksen käyttötapaus
Voit tuoda ympäristöjä mihin tahansa tiedostoon, kuten palveluihin clientUtilServices.ts
import {environment} from '../../environments/environment';getHostURL(): string {
return environment.apiHost;
}
Käyttötapaus rakenteessa
Avaa Angular CLI -tiedostosi .angular-cli.json ja lisää sisälle "apps": [{...}] seuraava koodi
"apps":[{
"environments": {
"dev": "environments/environment.ts",
"prod": "environments/environment.prod.ts",
"qa": "environments/environment.qa.ts",
}
}
]
Jos haluat rakentaa tuotantoon, suorita ng build --env=prod, se lukee konfiguraation tiedostosta environment.prod.ts, samalla tavalla voit tehdä sen myös qa tai dev varten
## Vanhempi vastaus
Olen tehnyt jotain alla olevan kaltaista omassa tarjoajassani:
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'
}
}
Sitten minulla on pääsy kaikkiin vakioihin tietoihin missä tahansa
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)
}
}
Vastaus #4
Angular2:ssa sinulla on seuraava provide-määritelmä, jonka avulla voit määrittää erilaisia riippuvuuksia:
provide(token: any, {useClass, useValue, useExisting, useFactory, deps, multi}
Vertailu Angular 1:een
app.service Angular1:ssä vastaa useClass:ia Angular2:ssa.
app.factory Angular1:ssä vastaa useFactory:a Angular2:ssa.
app.constant ja app.value on yksinkertaistettu useValue:ksi vähemmillä rajoituksilla. Eli config-lohkoa ei ole enää.
app.provider - Angular 2:ssa ei ole vastaavaa.
Esimerkkejä
Asettaaksesi juuripistorasian kanssa:
bootstrap(AppComponent,[provide(API_ENDPOINT, { useValue='http://127.0.0.1:6666/api/' })]);
Tai asenna komponenttisi injektorin avulla:
providers: [provide(API_ENDPOINT, { useValue: 'http://127.0.0.1:6666/api/'})]
provide on lyhenne muodosta:
var injectorValue = Injector.resolveAndCreate([
new Provider(API_ENDPOINT, { useValue: 'http://127.0.0.1:6666/api/'})
]);
Injektorin avulla arvon saaminen on helppoa:
var endpoint = injectorValue.get(API_ENDPOINT);
Vastaus #5
Angular 4:ssa voit käyttää ympäristöluokkaa pitääksesi kaikki globaalisi.
Sinulla on oletuksena environment.ts ja environment.prod.ts.
Esimerkiksi
export const environment = {
production: false,
apiUrl: 'http://localhost:8000/api/'
};
Ja sitten palveluksessasi:
import { environment } from '../../environments/environment';
...
environment.apiUrl;
Vastaus #6
Vaikka lähestymistapa, jossa on AppSettings-luokka ja merkkijonovakio ApiEndpoint, toimii, se ei ole ihanteellinen, koska emme pystyisi vaihtamaan tätä todellista ApiEndpoint-arvoa muihin arvoihin yksikkötestauksen aikana.
Meidän täytyy pystyä injektoimaan nämä API-päätepisteet palveluihimme (ajattele palvelun injektoimista toiseen palveluun). Emme myöskään tarvitse luoda kokonaista luokkaa tätä varten, kaikki mitä haluamme tehdä, on injektoida merkkijono palveluihimme, joka on meidän ApiEndpointimme. Täydennyksenä erinomaiselle vastaukselle, jonka pixelbits antoi, tässä on kokonainen koodi siitä, miten se voidaan tehdä Angular 2:ssa:
Ensinnäkin meidän täytyy kertoa Angularille, kuinka tarjota instanssi ApiEndpointistamme, kun pyydämme sitä sovelluksessamme (ajattele sitä riippuvuuden rekisteröimiseksi):
bootstrap(AppComponent, [
HTTP_PROVIDERS,
provide('ApiEndpoint', {useValue: 'http://127.0.0.1:6666/api/'})
]);
Ja sitten palvelussa injektoimme tämän ApiEndpointin palvelun konstruktoriin, ja Angular tarjoaa sen meille rekisteröintimme perusteella yllä:
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...
}
Vastaus #7
Tämä on minun tuore kokemus tästä tilanteesta:
- @angular/cli: 1.0.0
- solmu: 6.10.2
- @angular/core: 4.0.0
Olen seurannut virallisia ja päivitettyjä asiakirjoja täällä:
https://angular.io/docs/ts/latest/guide/dependency-injection.html#!#dependency-injection-tokens
Näyttää siltä, että OpaqueToken on nyt vanhentunut ja meidän on käytettävä InjectionToken, joten nämä ovat tiedostoni, jotka toimivat moitteettomasti:
app-konfiguraatio.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@
}
Tulos on siisti eikä konsolissa ole varoituksia kiitos John Papan äskettäisen kommentin tässä asiassa:
https://github.com/angular/angular-cli/issues/2034
Avain oli toteuttaa rajapinta eri tiedostossa.
Vastaus #8
Kaikki ratkaisut vaikuttavat olevan monimutkaisia. Etsin tämän tapauksen yksinkertaisinta ratkaisua ja haluan vain käyttää vakioita. Vakiot ovat yksinkertaisia. Onko mitään, mikä puhuisi seuraavaa ratkaisua vastaan?
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 );
}
}
Vastaus #9
Käytä vain Typescript-vakioarvoa
export var API_ENDPOINT = 'http://127.0.0.1:6666/api/';
Voit käyttää sitä riippuvuuden injektiossa käyttäen
bootstrap(AppComponent, [provide(API_ENDPOINT, {useValue: 'http://127.0.0.1:6666/api/'}), ...]);
