กำหนดค่าคงที่ทั่วโลก


258

ใน Angular 1.x คุณสามารถกำหนดค่าคงที่เช่นนี้:

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

สิ่งที่จะเทียบเท่าในเชิงมุม (กับ TypeScript)?

ฉันไม่ต้องการที่จะทำซ้ำ API ฐาน URL ซ้ำแล้วซ้ำอีกในบริการทั้งหมดของฉัน

คำตอบ:


265

การเปลี่ยนแปลงด้านล่างใช้ได้กับฉันในเวอร์ชันสุดท้าย Angular 2:

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

แล้วในการบริการ:

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);
    }
}

ผมคิดว่า Yout AppSettingsระดับที่ควรจะเป็นนามธรรมและสมาชิกควรจะเป็นAPI_ENDPOINT readonly
Philippe Gioseffi

164

วิธีการแก้ปัญหาสำหรับการกำหนดค่าที่มีให้บริการโดยทีมงานเชิงมุมตัวเองที่สามารถพบได้ที่นี่

นี่คือรหัสที่เกี่ยวข้องทั้งหมด:

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) your.service.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
    }   
}

ตอนนี้คุณสามารถฉีดการกำหนดค่าได้ทุกที่โดยไม่ต้องใช้ชื่อสตริงและด้วยการใช้อินเทอร์เฟซของคุณสำหรับการตรวจสอบแบบคงที่

แน่นอนคุณสามารถแยกส่วนต่อประสานและค่าคงที่เพิ่มเติมเพื่อให้สามารถระบุค่าที่แตกต่างในการผลิตและการพัฒนาเช่น


3
ใช้งานได้เฉพาะเมื่อฉันไม่ได้ระบุประเภทในตัวสร้างของบริการ ดังนั้นมันจะทำงานเมื่อฉันทำคอนสตรัค (@Inject (APP_CONFIG) การตั้งค่าส่วนตัว) {} มีการกล่าวถึงที่นี่เป็น blog.thoughtram.io/angular/2016/05/23/... แต่ไม่ว่าทำไม
Mukus

ฉันคิดว่าคุณพลาดคำสำคัญในการนำเข้าหรือส่งออกหรืออะไรทำนองนั้นเนื่องจากฉันใช้กับอินเทอร์เฟซและเป็นสิ่งที่คุณพูดว่าสำคัญมากที่จะต้องพิมพ์แบบคงที่อย่างชัดเจน บางทีคุณอาจต้องให้ข้อยกเว้นที่แน่นอนที่นี่
Ilya Chernomordik

46
ไม่มีวิธีแก้ปัญหาเหล่านี้แม้แต่ทีมงานเชิงมุมที่แนะนำก็ดูดี เหตุใดจึงพยายามสร้างค่าคงที่ที่ยุ่งยากใน Angular 2 คุณไม่เห็นว่า Angular1 ผลิตได้อย่างไร? ทำไมต้องเป็นระเบียบ?
KhoPhi

31
สำหรับคนอื่นที่ฮิตคำตอบนี้ OpaqueToken ใน v4 เชิงมุมคือ "เลิก" สำหรับ InjectionToken - blog.thoughtram.io/angular/2016/05/23/...
mtpultz

3
การใส่รหัสจากขั้นตอนที่ 1 เป็นเรื่องที่เหมาะสมenvironment.tsหรือไม่environment.prod.tsเพื่อให้คุณมีค่าคงที่แตกต่างกันต่อสภาพแวดล้อม @IlyaChernomordik เริ่มพูดถึงเรื่องนี้ในวรรคสุดท้ายของคำตอบของเขา
Robert Bernstein

64

ใน Angular2 คุณมีคำนิยามที่ให้ดังต่อไปนี้ซึ่งช่วยให้คุณสามารถตั้งค่าการพึ่งพาประเภทต่างๆ:

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

เปรียบเทียบกับเชิงมุม 1

app.serviceใน Angular1 เทียบเท่ากับuseClassใน Angular2

app.factoryใน Angular1 เทียบเท่ากับuseFactoryใน Angular2

app.constantและapp.valueถูกทำให้เรียบง่ายขึ้นuseValueโดยมีข้อ จำกัด น้อยลง นั่นคือไม่มีconfigบล็อกอีกต่อไป

app.provider - ไม่เทียบเท่าใน Angular 2

ตัวอย่าง

วิธีตั้งค่าด้วยหัวฉีดรูท:

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

หรือตั้งค่าด้วยหัวฉีดส่วนประกอบของคุณ:

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

provide มือสั้นสำหรับ:

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

ด้วยหัวฉีดการได้รับค่าเป็นเรื่องง่าย:

var endpoint = injectorValue.get(API_ENDPOINT);

2
จริง ๆ แล้วฉันต้องการที่จะมีการตั้งค่าของฉันในไฟล์ภายนอกเช่น: settings.ts ไฟล์นี้จะมีลักษณะอย่างไร
AndreFeijo

คุณได้พิจารณาจาวาสคริปต์ฝั่งเซิร์ฟเวอร์เช่น NodeJS หรือไม่?
pixelbits

5
ขออภัยฉันไม่เข้าใจว่าฉันจะฉีดลงในบริการของฉันได้อย่างไร ขณะที่ฉันใช้ไฟล์ภายนอกฉันต้องส่งออกหรือไม่
AndreFeijo

ฉันจะทำให้มันเป็นส่วนหนึ่งของกระบวนการกำหนดค่าการสร้างของคุณ นั่นคือขึ้นอยู่กับสภาพแวดล้อมของคุณคอมไพล์ / แพ็คเกจไฟล์ต่าง ๆ เข้าด้วยกันจากนั้นปรับใช้ ทั้งหมดนี้คุณสามารถทำได้กับ NodeJS ด้วยโมดูลที่เหมาะสม
pixelbits

1
NodeJS ไม่ใช่ตัวเลือกโชคไม่ดี
AndreFeijo

59

ใน Angular 4 คุณสามารถใช้คลาสสภาพแวดล้อมเพื่อเก็บกลมทั้งหมดของคุณ

คุณมี environment.ts และ environment.prod.ts เป็นค่าเริ่มต้น

ตัวอย่างเช่น

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

แล้วในการบริการของคุณ:

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

ถ้าคุณกำลังพยายามที่จะเข้าถึงconstด้านในของบริการที่คุณอาจจะต้อง "ให้" { provide: 'ConstName', useValue: ConstName }ในโมดูลของแอปผู้ให้บริการอาร์เรย์: ฉันได้รับข้อผิดพลาดรันไทม์โดยที่ไม่มีสิ่งนี้
daleyjem

@daleyem นั่นเป็นเพราะคุณกำลังพยายามที่จะฉีดมัน วิธีนี้ไม่ได้ใช้หัวฉีด
Aluan Haddad

การสร้างค่าคงที่เช่นนี้เป็นสิ่งที่ง่ายที่สุด ฉันเดาว่าการโต้เถียงของการสูญเสีย DI และการสูญเสียความสามารถในการทดสอบ / mockValue นั้นนานเกินไป ในแอปทั่วไปเราใช้ส่วนประกอบที่ไม่ใช่ DI เช่น (RxJS) มากมายโดยไม่รบกวนการทดสอบ
Amitesh

54

อัปเดตสำหรับ Angular 4+

ตอนนี้เราสามารถใช้ไฟล์สภาพแวดล้อมซึ่งเป็นมุมให้ค่าเริ่มต้นหากโครงการของคุณถูกสร้างขึ้นผ่าน angular-cli

ตัวอย่างเช่น

ในโฟลเดอร์สภาพแวดล้อมของคุณสร้างไฟล์ต่อไปนี้

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

และแต่ละไฟล์สามารถระงับการเปลี่ยนแปลงรหัสที่เกี่ยวข้องเช่น:

  • 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' ],
    };

ใช้ตัวพิมพ์ในแอปพลิเคชัน

คุณสามารถนำเข้าสภาพแวดล้อมไปยังไฟล์ใด ๆ เช่นบริการ clientUtilServices.ts

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

getHostURL(): string {
    return environment.apiHost;
  }

ใช้ตัวพิมพ์ในบิลด์

เปิดไฟล์ CLI เชิงมุมของคุณ.angular-cli.jsonและ"apps": [{...}]เพิ่มรหัสต่อไปนี้ภายใน

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

หากคุณต้องการสร้างเพื่อการผลิตเรียกใช้ ng build --env=prodจะอ่านการกำหนดค่าจาก environment.prod.tsแบบเดียวกับที่คุณสามารถทำได้สำหรับqaหรือdev

## คำตอบที่เก่ากว่า

ฉันได้ทำบางอย่างเช่นด้านล่างในผู้ให้บริการของฉัน:

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'
  }
}

จากนั้นฉันก็สามารถเข้าถึงข้อมูลคงที่ได้ทุกที่

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)
  }
 }

6
สิ่งนี้ไม่ทำงานเหมือนค่าคงที่ ค่าของค่าคงที่จะเท่ากันเสมอ ในกรณีของAPI_ENDPOINTคุณค่าของคุณสามารถเขียนทับได้ตลอดเวลา หากthis.ConstantService.API_ENDPOINT = 'blah blah'มีการประกาศในชั้นเรียนได้ตลอดเวลาหลังจากที่คุณเรียกว่า "คงที่" ถูกนำเข้ามาจากconstant-serviceค่าใหม่ API_ENDPOINT 'blah blah'จะเป็น โซลูชันของคุณเพียงแสดงวิธีเข้าถึงตัวแปรโดยใช้บริการและไม่ใช้ค่าคงที่
Devner

1
@Devner ทำให้พวกเขาอ่านได้อย่างเดียวreadonly API_ENDPOINT :String;
Flavien Volken

@Anjum วิธีเลือกมุมไฟล์ env ฉันต้องส่งชื่อ env ในขณะที่เริ่มต้นแอพหรือไม่
notionquest

@notionquest ใช่คุณสามารถผ่านมันได้เช่นng build --env=prod
Anjum ....

31

ในขณะที่วิธีการที่มีคลาส AppSettings ที่มีค่าคงที่สตริงเป็น ApiEndpoint ก็ไม่เหมาะเนื่องจากเราจะไม่สามารถแลกเปลี่ยน ApiEndpoint จริงนี้สำหรับค่าอื่น ๆ ในขณะที่ทำการทดสอบหน่วย

เราต้องสามารถฉีดจุดปลาย api นี้ลงในบริการของเรา (คิดว่าเป็นการฉีดบริการลงในบริการอื่น) เราไม่จำเป็นต้องสร้างคลาสทั้งหมดสำหรับสิ่งนี้สิ่งที่เราต้องทำคือการฉีดสตริงเข้าไปในบริการของเราเป็น ApiEndpoint ของเรา เพื่อให้ได้คำตอบที่ดีเยี่ยมโดยpixelbitsนี่คือรหัสที่สมบูรณ์เกี่ยวกับวิธีที่สามารถทำได้ใน Angular 2:

ก่อนอื่นเราต้องบอก Angular ว่าจะให้อินสแตนซ์ของ ApiEndpoint ของเราได้อย่างไรเมื่อเราขอในแอพของเรา (คิดว่าเป็นการลงทะเบียนการพึ่งพา):

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


จากนั้นในการให้บริการเราฉีด ApiEndpoint นี้ไปยังตัวสร้างบริการและ Angular จะจัดหาให้เราตามการลงทะเบียนของเราด้านบน:

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...
}

1
ขณะนี้มีวิธีการ "ทำอย่างเป็นทางการ" ในการแนะนำโดยทีมงานเชิงมุมในบทช่วยสอน ฉันได้เพิ่มคำตอบด้านล่าง: ( stackoverflow.com/a/40287063/1671558 )
Ilya Chernomordik

1
รหัสนี้ไม่ถูกต้องอีกต่อไปการใช้สิ่งนี้จะทำให้ ApiEndpoint ไม่พบใน AppComponent
WilliamX

ตกลงฉันไม่ได้อยู่คนเดียว คุณรู้หรือไม่ว่ารุ่นนี้พังไหม มีวิธีอื่นที่ไม่ต้องการกำหนดค่าบนวัตถุส่วนกลางแล้วให้พวกเขาหรือไม่
Jens Bodal

29

นี่คือประสบการณ์ล่าสุดของฉันกับสถานการณ์นี้:

  • @ angular / cli: 1.0.0
  • โหนด: 6.10.2
  • @ angular / core: 4.0.0

ฉันได้ติดตามเอกสารอย่างเป็นทางการและอัปเดตแล้วที่นี่:

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

ตอนนี้ดูเหมือนว่าOpaqueTokenเลิกใช้แล้วและเราต้องใช้InjectionTokenดังนั้นไฟล์เหล่านี้ของฉันจึงทำงานอย่างมีเสน่ห์:

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@

  }

ผลลัพธ์นั้นสะอาดและไม่มีคำเตือนบนคอนโซลขอบคุณความคิดเห็นล่าสุดของ John Papa ในเรื่องนี้:

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

กุญแจถูกนำไปใช้ในไฟล์ที่แตกต่างอินเตอร์เฟซ


ดูstackoverflow.com/a/43193574/3092596 - ซึ่งเป็นพื้นเดียวกัน แต่สร้างโมดูลฉีดมากกว่าผู้ให้บริการ
goredwards

19

การแก้ปัญหาทั้งหมดดูเหมือนจะซับซ้อน ฉันกำลังมองหาวิธีแก้ปัญหาที่ง่ายที่สุดสำหรับกรณีนี้และฉันแค่ต้องการใช้ค่าคงที่ ค่าคงที่ง่าย มีอะไรที่พูดกับวิธีแก้ปัญหาต่อไปนี้หรือไม่?

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 );
    }

}

2
คุณกำลังใช้ตัวแปรที่อยู่นอกขอบเขตของบริการดังนั้นคุณก็สามารถใช้หน้าต่างกลมได้ สิ่งที่เราพยายามทำคือนำค่าคงที่เข้าสู่ระบบฉีดขึ้นรูปของ Angular4 เพื่อให้เราสามารถรักษาความสะอาดขอบเขตไม่คงที่หรือเยาะเย้ยได้
Joel Hernandez

11

เพียงใช้ค่าคงที่ typescript

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

คุณสามารถใช้มันในการใช้หัวฉีดพึ่งพา

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

1
ทำไมต้องฉีด ฉันไม่จำเป็นต้องคิดว่า ... คุณสามารถใช้งานได้ทันทีที่คุณนำเข้า @SnareChops
Sasxa

@Sasxa ฉันเห็นด้วยแม้ว่ามันอาจจะดีสำหรับการทดสอบหน่วยและเช่น เพียงแค่พยายามให้คำตอบที่สมบูรณ์
SnareChops

1
@Andreas คุณสามารถใช้constyest
SnareChops

โปรดระบุ stackblitz ของการทำงานนี้ ฉันได้เห็นตัวอย่างมากมายในการให้บริการในวิธีบูตสแตรป แต่ยังไม่พบตัวอย่างที่มีตัวอย่างการทำงานที่เพียงพอ อาจมีบางสิ่งที่เปลี่ยนแปลงไปในรุ่นที่ใหม่กว่าของเชิงมุม
Jens Bodal

4

หากคุณใช้Webpackซึ่งฉันแนะนำคุณสามารถตั้งค่าคงที่สำหรับสภาพแวดล้อมที่แตกต่างกัน สิ่งนี้มีค่ามากเป็นพิเศษเมื่อคุณมีค่าคงที่ที่แตกต่างกันตามสภาพแวดล้อม

คุณอาจมีไฟล์/configwebpack หลายไฟล์ในไดเรกทอรีของคุณ(เช่น webpack.dev.js, webpack.prod.js เป็นต้น) แล้วคุณจะมีcustom-typings.d.tsคุณจะเพิ่มพวกเขาที่นั่น นี่คือรูปแบบทั่วไปที่จะติดตามในแต่ละไฟล์และตัวอย่างการใช้งานใน Component

webpack. {} env .js

const API_URL = process.env.API_URL = 'http://localhost:3000/';
const JWT_TOKEN_NAME = "id_token";
...
    plugins: [
      // NOTE: when adding more properties, make sure you include them in custom-typings.d.ts
      new DefinePlugin({
        'API_URL': JSON.stringify(API_URL),
        'JWT_TOKEN_NAME': JSON.stringify(JWT_TOKEN_NAME)
      }),

-typings.d.ts ที่กำหนดเอง

declare var API_URL: string;
declare var JWT_TOKEN_NAME: string;
interface GlobalEnvironment {
  API_URL: string;
  JWT_TOKEN_NAME: string;
}

ตัวแทน

export class HomeComponent implements OnInit {
  api_url:string = API_URL;
  authToken: string = "Bearer " + localStorage.getItem(JWT_TOKEN_NAME)});
}

3

การใช้ไฟล์คุณสมบัติที่สร้างขึ้นในระหว่างการบิลด์นั้นง่ายและสะดวก นี่คือวิธีการที่ Angular CLI ใช้ กำหนดไฟล์คุณสมบัติสำหรับแต่ละสภาพแวดล้อมและใช้คำสั่งระหว่างบิลด์เพื่อกำหนดไฟล์ที่จะถูกคัดลอกไปยังแอปของคุณ จากนั้นเพียงนำเข้าไฟล์คุณสมบัติที่จะใช้

https://github.com/angular/angular-cli#build-targets-and-environment-files


3

วิธีการหนึ่งสำหรับ Angular4 จะกำหนดค่าคงที่ที่ระดับโมดูล:

const api_endpoint = 'http://127.0.0.1:6666/api/';

@NgModule({
  declarations: [AppComponent],
  bootstrap: [AppComponent],
  providers: [
    MessageService,
    {provide: 'API_ENDPOINT', useValue: api_endpoint}
  ]
})
export class AppModule {
}

จากนั้นในการบริการของคุณ:

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

@Injectable()
export class MessageService {

    constructor(private http: Http, 
      @Inject('API_ENDPOINT') private api_endpoint: string) { }

    getMessages(): Observable<Message[]> {
        return this.http.get(this.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);
    }
}

3

ฉันมีวิธีอื่นในการกำหนดค่าคงที่ทั่วโลก เพราะถ้าเรากำหนดไว้ในไฟล์ ts ถ้าสร้างในโหมดการผลิตมันไม่ง่ายเลยที่จะหาค่าคงที่เพื่อเปลี่ยนค่า

export class SettingService  {

  constructor(private http: HttpClient) {

  }

  public getJSON(file): Observable<any> {
      return this.http.get("./assets/configs/" + file + ".json");
  }
  public getSetting(){
      // use setting here
  }
}

ในโฟลเดอร์แอพฉันเพิ่มโฟลเดอร์ configs / setting.json

เนื้อหาใน setting.json

{
    "baseUrl": "http://localhost:52555"
}

ในโมดูลแอปเพิ่ม APP_INITIALIZER

   {
      provide: APP_INITIALIZER,
      useFactory: (setting: SettingService) => function() {return setting.getSetting()},
      deps: [SettingService],
      multi: true
    }

ด้วยวิธีนี้ฉันสามารถเปลี่ยนค่าในไฟล์ json ได้ง่ายขึ้น ฉันยังใช้วิธีนี้สำหรับข้อความแสดงข้อผิดพลาด / คำเตือนคงที่


0

AngularJS ของ module.constantไม่ได้กำหนดค่าคงที่ในความหมายมาตรฐาน

ในขณะที่มันยืนอยู่บนตัวมันเองเป็นกลไกการลงทะเบียนผู้ให้บริการ แต่เป็นที่เข้าใจกันดีที่สุดในบริบทของฟังก์ชันmodule.value( $provide.value) ที่เกี่ยวข้อง เอกสารอย่างเป็นทางการระบุกรณีการใช้อย่างชัดเจน:

ลงทะเบียนบริการที่มีมูลค่าด้วย $ injector เช่นสตริงตัวเลขอาร์เรย์วัตถุหรือฟังก์ชัน สิ่งนี้สั้นสำหรับการลงทะเบียนบริการโดยที่คุณสมบัติ $ get ของผู้ให้บริการเป็นฟังก์ชั่นจากโรงงานที่ไม่มีข้อโต้แย้งและคืนค่าบริการ นั่นหมายความว่ามันเป็นไปไม่ได้ที่จะฉีดบริการอื่น ๆ เข้าไปในบริการที่มีคุณค่า

เปรียบเทียบสิ่งนี้กับเอกสารสำหรับmodule.constant( $provide.constant) ซึ่งระบุกรณีการใช้อย่างชัดเจน (เน้นที่เหมือง):

ลงทะเบียนบริการแบบคงที่ด้วย $ injector เช่นสตริงตัวเลขอาร์เรย์วัตถุหรือฟังก์ชัน เช่นเดียวกับค่าคุณไม่สามารถฉีดบริการอื่น ๆ ให้คงที่ได้ แต่แตกต่างจากค่าคงที่สามารถฉีดเข้าไปในฟังก์ชั่นการตั้งค่าโมดูล (ดู angular.Module) และไม่สามารถแทนที่โดยมัณฑนากร

ดังนั้นconstantฟังก์ชั่นAngularJS ไม่ได้ให้ค่าคงที่ในความหมายที่เข้าใจกันโดยทั่วไปของคำในฟิลด์

ที่กล่าวว่าข้อ จำกัด ที่วางไว้บนวัตถุที่ให้ไว้พร้อมกับความพร้อมก่อนหน้านี้ผ่านทาง $ injector แสดงให้เห็นชัดเจนว่ามีการใช้ชื่อโดยการเปรียบเทียบ

หากคุณต้องการค่าคงที่ที่แท้จริงในแอปพลิเคชัน AngularJS คุณจะต้อง "ให้" หนึ่งวิธีเช่นเดียวกับที่คุณทำในโปรแกรม JavaScript ใด ๆ ซึ่งเป็น

export const π = 3.14159265;

ใน Angular 2 จะใช้เทคนิคเดียวกัน

แอปพลิเคชัน Angular 2 ไม่มีเฟสการกำหนดค่าในลักษณะเดียวกับแอปพลิเคชัน AngularJS นอกจากนี้ยังไม่มีกลไกมัณฑนากรบริการ ( AngularJS Decorator ) แต่นี่ก็ไม่น่าประหลาดใจเป็นพิเศษเนื่องจากความแตกต่างระหว่างกัน

ตัวอย่างของ

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

โดยพลการและวางตัวเล็กน้อยเนื่องจาก$provide.constantใช้เพื่อระบุวัตถุที่เป็นค่าคงที่โดยบังเอิญ คุณอาจจะเขียนเช่นกัน

export const apiEndpoint = 'http://127.0.0.1:6666/api/';

สำหรับทั้งสามารถเปลี่ยนแปลง

ตอนนี้อาร์กิวเมนต์สำหรับความสามารถในการทดสอบการเยาะเย้ยค่าคงที่จะลดลงเพราะแท้จริงแล้วจะไม่เปลี่ยนแปลง

ไม่มีใครเยาะเย้ยπ

แน่นอนว่าความหมายเฉพาะของแอปพลิเคชันของคุณอาจเป็นที่จุดสิ้นสุดของคุณสามารถเปลี่ยนแปลงได้หรือ API ของคุณอาจมีกลไกการเฟลโอเวอร์ที่ไม่โปร่งใสดังนั้นจึงเหมาะสมสำหรับจุดสิ้นสุดของ API ที่จะเปลี่ยนแปลงภายใต้สถานการณ์บางอย่าง

แต่ในกรณีนั้นการระบุว่าเป็นการแสดงตัวอักษรสตริงของ URL เดียวกับconstantฟังก์ชันจะไม่ทำงาน

ข้อโต้แย้งที่ดีกว่าและน่าจะมีอีกหนึ่งเหตุผลที่สอดคล้องกับการมีอยู่ของ$provide.constantฟังก์ชันAngularJS คือเมื่อ AngularJS ถูกนำเสนอ JavaScript ไม่มีแนวคิดโมดูลมาตรฐาน ในกรณีนั้นจะใช้ globals เพื่อแบ่งปันค่าไม่แน่นอนหรือไม่เปลี่ยนรูปและการใช้ globals เป็นปัญหา

ที่กล่าวว่าการให้สิ่งนี้ผ่านกรอบเพิ่มการมีเพศสัมพันธ์กับกรอบที่ นอกจากนี้ยังผสมตรรกะเฉพาะเชิงมุมกับตรรกะที่จะทำงานในระบบอื่น ๆ

นี่ไม่ใช่การบอกว่ามันเป็นวิธีที่ผิดหรือเป็นอันตราย แต่โดยส่วนตัวถ้าฉันต้องการค่าคงที่ในแอปพลิเคชัน Angular 2 ฉันจะเขียน

export const π = 3.14159265;

เช่นเดียวกับที่ฉันเคยใช้ AngularJS

ยิ่งมีการเปลี่ยนแปลง ...


0

วิธีที่ดีที่สุดในการสร้างค่าคงที่ของแอพพลิเคชั่นใน Angular 2 คือการใช้ไฟล์ environment.ts ข้อดีของการประกาศค่าคงที่เช่นนี้คือคุณสามารถเปลี่ยนแปลงค่าได้ตามสภาพแวดล้อมเนื่องจากอาจมีไฟล์สภาพแวดล้อมที่แตกต่างกันสำหรับแต่ละสภาพแวดล้อม


สิ่งนี้จะไม่ทำงานหากคุณต้องการสร้างแอปพลิเคชันของคุณเพียงครั้งเดียวจากนั้นปรับใช้กับสภาพแวดล้อมที่หลากหลาย
Jens Bodal

-1

คุณสามารถสร้างคลาสสำหรับตัวแปรโกลบอลของคุณจากนั้นเอ็กซ์พอร์ตคลาสนี้เช่นนี้:

export class CONSTANT {
    public static message2 = [
        { "NAME_REQUIRED": "Name is required" }
    ]

    public static message = {
        "NAME_REQUIRED": "Name is required",
    }
}

หลังจากสร้างและส่งออกCONSTANTชั้นเรียนของคุณแล้วคุณควรนำเข้าชั้นเรียนนี้ในชั้นเรียนที่คุณต้องการใช้เช่นนี้

import { Component, OnInit                       } from '@angular/core';
import { CONSTANT                                } from '../../constants/dash-constant';


@Component({
  selector   : 'team-component',
  templateUrl: `../app/modules/dashboard/dashComponents/teamComponents/team.component.html`,
})

export class TeamComponent implements OnInit {
  constructor() {
    console.log(CONSTANT.message2[0].NAME_REQUIRED);
    console.log(CONSTANT.message.NAME_REQUIRED);
  }

  ngOnInit() {
    console.log("oninit");
    console.log(CONSTANT.message2[0].NAME_REQUIRED);
    console.log(CONSTANT.message.NAME_REQUIRED);
  }
}

คุณสามารถใช้วิธีนี้ทั้งในconstructorหรือngOnInit(){}หรือในวิธีที่กำหนดไว้ล่วงหน้าใด ๆ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.