【问题标题】:Define global constants定义全局常量
【发布时间】:2016-05-01 10:15:10
【问题描述】:

在 Angular 1.x 中,您可以像这样定义常量:

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

Angular(使用 TypeScript)中的等价物是什么?

我只是不想在我的所有服务中一遍又一遍地重复 API 基本 URL。

【问题讨论】:

    标签: typescript angular


    【解决方案1】:

    在阅读了该主题的所有答案以及其他一些答案后,我想提供我这些天正在使用的解决方案。

    首先我必须为环境添加一个类。有了这个,我实现了我的属性的数据类型,所以它很容易使用。此外,我可以将默认数据绑定到我的环境,这样我就可以在所有环境之间共享公共数据。有时我们有一些在所有环境中具有相同值的变量(例如站点名称),我们不想每次都更改为所有环境。

    // environments\ienvironments.ts
    
    export class IEnvironment implements IEnvironmentParams {
      public production: boolean;
      public basicURL: string = 'https://www.someawesomedomain.com';
      public siteName: string = 'My awesome site';
    
      constructor(params: IEnvironmentParams) {
        this.production = params.production ?? false;
        this.basicURL = params.basicURL ?? this.basicURL;
        this.siteName = params.siteName ?? this.siteName;
      }
    }
    
    export interface IEnvironmentParams {
      production: boolean;
      basicURL?: string;
      siteName?: string;
    }
    

    请注意,我使用 IEnvironmentParams 来简化环境的创建,这样我可以传递对象而不会弄乱构造函数参数并避免参数顺序问题,还可以使用 @987654326 提供所需的默认值功能@运算符。

    // environments\environment.prod.ts
    
    import {IEnvironment, IEnvironmentParams} from "./ienvironment";
    
    const params: IEnvironmentParams = {
        production: true
    };
    
    export const environment: IEnvironment = new IEnvironment(params);
    
    // environments\environment.ts
    
    import {IEnvironment, IEnvironmentParams} from "./ienvironment";
    
    const params: IEnvironmentParams = {
        production: false
    };
    
    export const environment: IEnvironment = new IEnvironment(params);
    

    用法示例

    import {environment} from "../environments/environment";
    
    
    // app-routing.module.ts
    
    const routes: Routes = [
      { 
        path: '', component: HomeComponent,     
        data: {
            title: `${environment.siteName} | Home page title!`,
            description: 'some page description',
        }
      }
    ];
    

    检查代码完成情况。

    // home.component.ts
    
    @Component({
      selector: 'app-home',
      templateUrl: './home.component.html',
      styleUrls: ['./home.component.scss']
    })
    export class HomeComponent {
    
      constructor() {
        console.log(`home component constructor - showing evironment.siteName - ${environment.siteName}`);
      }
    }
    

    你可以在任何你想要的地方使用它,类、服务、指令、组件等。

    对于那些想在构建后替换值的人。你能行的。这有点棘手,但是当您构建 Angular 应用程序时,环境数据会导出到 main.js,请看下一个屏幕截图。

    只需在任何 IDE 中打开文件并找到 environment 然后替换数据即可。

    关于 Angular Universal 项目。构建 Angular Universal 项目时,它将导出 2 个main.js,一个用于服务器,一个用于浏览器,因此您必须同时更改两者。

    【讨论】:

      【解决方案2】:

      我还有另一种定义全局常量的方法。因为如果我们在 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
        }
      }
      

      在 app 文件夹中,我添加文件夹 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 文件中的值。 我也将这种方式用于不断的错误/警告消息。

      【讨论】:

      • 我无法使用这个答案。描述根本不够。有空请说明使用情况。
      【解决方案3】:

      所有解决方案似乎都很复杂。我正在为这种情况寻找最简单的解决方案,我只想使用常量。常数很简单。有什么反对以下解决方案的吗?

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

      【讨论】:

      • 好吧,您正在使用服务范围之外的变量,因此您也可以使用窗口全局变量。我们正在尝试做的是让常量进入 Angular4 依赖注入系统,这样我们就可以保持范围干净、可存根或可模拟。
      【解决方案4】:

      angular团队自己提供的配置解决方案,可以找到here

      以下是所有相关代码:

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

      现在您可以在任何地方注入配置,而无需使用字符串名称并使用您的接口进行静态检查。

      您当然可以进一步分离接口和常量,以便能够在生产和开发中提供不同的值,例如

      【讨论】:

      • 它只在我没有在服务的构造函数中指定类型时才有效。所以当我做构造函数时它起作用(@Inject(APP_CONFIG) private config){}这里提到了这个:blog.thoughtram.io/angular/2016/05/23/… 但不是为什么。
      • 我想你错过了一些 import 或 export 关键字或类似的东西,因为我将它与界面一起使用,正如你所说,让它显式静态输入非常重要。也许您需要在此处提供确切的例外情况。
      • 这些解决方案都不是,即使是 Angular 团队推荐的方法看起来也很优雅。为什么尝试在 Angular 2 中创建常量是一个繁琐的过程?你看不出 Angular1 是如何做到无缝衔接的吗?为什么这么乱?
      • 对于遇到此答案的其他人来说,Angular v4 中的 OpaqueToken 对于 InjectionToken - blog.thoughtram.io/angular/2016/05/23/… “已弃用”
      • 将步骤 1 中的代码放入 environment.tsenvironment.prod.ts 是否有意义,以便您可以在每个环境中使用不同的常量? @IlyaChernomordik 在他回答的最后一段中开始提到这一点。
      【解决方案5】:

      为 Angular 4+ 更新

      如果您的项目是通过 angular-cli 生成的,现在我们可以简单地使用 angular 提供默认值的环境文件。

      例如

      在您的环境文件夹中创建以下文件

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

      构建中的用例

      打开您的 Angular 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 读取配置,你可以为 qadev 做同样的事情

      ## 旧答案

      我一直在我的提供商中做如下的事情:

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

      【讨论】:

      • 这不像常量那样工作。常量的值始终相同。在您的情况下,您的 API_ENDPOINT 值可以在任何时间点被覆盖。如果在从constant-service 导入所谓的“常量”之后的任何时候在类中声明this.ConstantService.API_ENDPOINT = 'blah blah',API_ENDPOINT 的新值将是'blah blah'。您的解决方案只是展示了如何使用服务而不是使用常量来访问变量。
      • @Devner 将它们设为只读 readonly API_ENDPOINT :String;
      • @Anjum 角度如何选择 env 文件。启动应用程序时是否需要传递环境名称?
      • @notionquest 是的,你可以通过它,比如ng build --env=prod
      • 我同意@Devner。常量和环境变量之间有一个非常明显的区别。环境变量相当灵活,可以针对不同的部署实例进行更改。常量,例如路由名称不需要针对不同的实例进行更改。否则,你最终会膨胀 env 文件
      【解决方案6】:

      在 Angular 2 中创建应用程序范围常量的最佳方法是使用 environment.ts 文件。声明此类常量的好处是您可以根据环境改变它们,因为每个环境可以有不同的环境文件。

      【讨论】:

      • 如果您打算构建应用程序然后将其部署到多个环境,则此方法不起作用。
      • @JensBodal:是的,我也有同样的问题。使用环境文件似乎是一个干净的设计,除了你不能使用你的 pre-prod 构建进行生产。此外,它需要在开发环境中进行生产设置,这有时会带来安全问题。
      【解决方案7】:

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

      【讨论】:

        【解决方案8】:

        在 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,您可能必须在应用模块的providers 数组中“提供”它:{ provide: 'ConstName', useValue: ConstName }。如果没有这个,我会遇到运行时错误。
        • @daleyjem 那是因为你试图注入它。这种方法不使用注入器
        • 像这样创建一个常量是最简单的。我猜想失去 DI 从而失去可测试性/mockValue 的反论点有些时候被夸大了。在典型的应用程序中,我们使用了很多非 DI 组件,例如 (RxJS),而不会影响可测试性。
        【解决方案9】:

        这是我最近对这种情况的体验:

        • @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

        关键是在不同的文件中实现接口。

        【讨论】:

        【解决方案10】:

        AngularJS 的module.constant 没有定义标准意义上的常量。

        虽然它作为提供者注册机制独立存在,但最好在相关的 module.value ($provide.value) 函数的上下文中理解。官方文档清楚地说明了用例:

        用 $injector 注册一个值服务,例如字符串、数字、数组、对象或函数。这是注册服务的缩写,其中提供者的 $get 属性是一个工厂函数,不接受任何参数并返回值服务。这也意味着不可能将其他服务注入到价值服务中。

        将此与module.constant ($provide.constant) 的文档进行比较,后者也清楚地说明了用例(强调我的):

        用$injector注册一个常量服务,如字符串、数字、数组、对象或函数。像值一样,不可能将其他服务注入常量。 但与 value 不同的是,常量可以注入到模块配置函数中(参见 angular.Module),并且不能被 AngularJS 装饰器覆盖

        因此,AngularJS constant 函数没有提供字段中术语的通常理解含义的常量。

        也就是说,对提供的对象施加的限制,以及它通过 $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 函数是行不通的。

        一个更好的论点,可能更符合 AngularJS $provide.constant 函数存在的原因是,当 AngularJS 被引入时,JavaScript 没有 标准 模块概念。在这种情况下,全局变量将用于共享可变或不可变的值,并且使用全局变量是有问题的。

        也就是说,通过框架提供这样的东西会增加与该框架的耦合。它还将 Angular 特定的逻辑与适用于任何其他系统的逻辑混合在一起。

        这并不是说这是一种错误或有害的方法,但就个人而言,如果我想在 Angular 2 应用程序中使用 constant,我会写

        export const π = 3.14159265;
        

        就像我使用 AngularJS 一样。

        变化越多……

        【讨论】:

          【解决方案11】:

          你可以为你的全局变量创建一个类,然后像这样导出这个类:

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

          您可以在constructorngOnInit(){} 或任何预定义方法中使用它。

          【讨论】:

            【解决方案12】:

            如果您使用我推荐的Webpack,您可以为不同的环境设置常量。当您在每个环境中具有不同的常量值时,这尤其有价值。

            /config 目录下可能有多个 webpack 文件(例如,webpack.dev.js、webpack.prod.js 等)。然后你会有一个custom-typings.d.ts,你会在那里添加它们。以下是每个文件中要遵循的一般模式以及组件中的示例用法。

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

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

            【讨论】:

              【解决方案13】:

              以下更改适用于 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);
                  }
              }
              

              【讨论】:

              • 我认为 AppSettings 类应该是抽象的,API_ENDPOINT 成员应该是 readonly
              【解决方案14】:

              在 Angular2 中,您有以下 provide 定义,它允许您设置不同类型的依赖项:

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

              与 Angular 1 相比

              Angular1 中的app.service 等价于Angular2 中的useClass

              Angular1 中的app.factory 等价于Angular2 中的useFactory

              app.constantapp.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);
              

              【讨论】:

              • 我实际上想将我的设置放在一个外部文件中,例如:settings.ts 这个文件是什么样子的?
              • 您是否考虑过 NodeJS 等服务器端 javascript?
              • 抱歉,我不明白如何将它注入到我的服务中?由于我使用的是外部文件,我需要将其导出吗?
              • 我会让它成为您构建配置过程的一部分。即根据您的环境,将不同的文件编译/打包在一起,然后部署。所有这些你都可以用 NodeJS 和适当的模块来完成。
              • NodeJS 不是一个选项,不幸的是。
              【解决方案15】:

              使用在构建过程中生成的属性文件既简单又容易。这是 Angular CLI 使用的方法。为每个环境定义一个属性文件,并在构建期间使用命令来确定将哪个文件复制到您的应用程序。然后只需导入要使用的属性文件。

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

              【讨论】:

                【解决方案16】:

                虽然使用带有字符串常量的 AppSettings 类作为 ApiEndpoint 的方法有效,但它并不理想,因为我们无法在单元测试时将这个真实的 ApiEndpoint 交换为其他一些值。

                我们需要能够将这个 api 端点注入到我们的服务中(想想将一个服务注入到另一个服务中)。我们也不需要为此创建一个完整的类,我们要做的就是将一个字符串注入到我们的服务中,作为我们的 ApiEndpoint。要完成excellent answer by 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...
                }
                

                【讨论】:

                • 现在 Angular 团队在他们的教程中推荐了一种“官方”方式。我在下面添加了一个答案:(stackoverflow.com/a/40287063/1671558)
                • 这段代码已经不准确了,实现这个会导致在AppComponent上找不到ApiEndpoint。
                • 好的,我并不孤单。你知道这个破的是哪个版本吗?是否有另一种方法不需要在全局对象上定义值然后提供它们?
                【解决方案17】:

                只需使用 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/'}), ...]);
                

                【讨论】:

                • 为什么要注入它?我认为不需要...您一导入就可以使用它。 @SnareChops
                • @Sasxa 我同意,尽管它可能对单元测试等有好处。只是想提供一个完整的答案。
                • @Andreas 你可以使用constyest
                • 请提供此工作的堆栈闪电。我见过很多在引导方法中提供服务的例子,但还没有找到一个足够有效的例子。可能在更新版本的 Angular 中发生了一些变化。
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多