Angular 2:基于环境导入服务

时间:2017-04-10 16:48:20

标签: angular

根据angular-cli项目中的当前环境导入服务的最佳/正确方法是什么?

我已经建立了一个名为dev-mock的新环境,我可以用它来调用...

ng serve --environment=mock

然后我使用useClass

在模块中设置提供程序

app / app.module.ts ...

import {environment} from '../environments/environment';
import {ApiService} from './api/api.service';
import {MockApiService} from './api/mock/mock-api.service';

@NgModule({
  declarations: [
    AppComponent,
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule
  ],
  providers: [
    {
      provide: ApiService,
      useClass: (environment.name === 'dev-mock') ? MockApiService : ApiService
    }
  ],
  bootstrap: [AppComponent]
})

这很好用,问题就是当我想将它注入另一个服务或组件时,我该怎么做,例如......

应用程序/票据/ ticket.service.ts

import {ApiService} from '../api/api.service'; // *** WHAT AM I TO DO HERE? ***

@Injectable()
export class TicketService {

  constructor(private api: ApiService, private http: Http) {
  }

}

显然我的做法是错误的。什么是正确的方法?

2 个答案:

答案 0 :(得分:2)

为MockApiService和ApiService创建接口,例如。 IApiService。如果你想要交换它们,就必须有一个。

使用令牌创建一个文件并将其导出:

import { OpaqueToken } from '@angular/core';
export let API_SERVICE = new OpaqueToken('api.service');

然后使用令牌在某处注册您的服务:

const apiServiceClass = (environment.name === 'dev-mock') ? MockApiService : ApiService;

providers: [{ provide: API_SERVICE, useClass: apiServiceClass }]

最后,您可以在构造函数中使用Inject()装饰器的任何地方使用它,例如

import {IApiService} from '../api/iapi.service';
import { Inject, Injectable } from '@angular/core';

@Injectable()
export class TicketService {

  constructor(@Inject(API_SERVICE) private api: IApiService) {}
}

诀窍是将接口作为属性类型使用,并使用带有OpaqueToken的Inject()告诉依赖注入器它应该放置什么。

答案 1 :(得分:0)

在我的库中,我使用的是定义通用环境变量的抽象环境类。

export abstract class Environment {
  abstract readonly production: boolean;
  abstract readonly appUrls: {
    readonly public: string;
    readonly portal: string;
    readonly admin: string;
  };
}

然后我将environment.ts文件更改如下。

import { Environment } from '@my-lib-prefix/common';

class EnvironmentImpl implements Environment {
  production = false;
  appUrls = {
    public: 'http://localhost:4200',
    portal: 'http://localhost:4201',
    admin: 'http://localhost:4202'
  };
}

export const environment = new EnvironmentImpl();

当然,environment.prod.ts与dev environment.ts是对称的。然后,在根目录app.module.ts中为每个Angular应用程序提供各自的环境依赖性。

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { Environment } from '@my-lib-prefix/common';
import { environment } from '../environments/environment';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  providers: [{ provide: Environment, useValue: environment }],
  bootstrap: [AppComponent]
})
export class AppModule {}

现在,任何组件都可以以干净,通用的方式注入环境依赖项。

import { Component } from '@angular/core';
import { Environment } from '@my-lib-prefix/common';

    @Component({
      selector: 'my-login',
      templateUrl: './my-login.component.html'
    })
    export class MyLoginComponent {
      constructor(private env: Environment) {}
    }

它强制执行每个environment.ts以实现抽象类中定义的“公共”环境变量。此外,每个相应的EnvironmentImpl都可以使用针对应用的特定环境变量进行扩展。这种方法看起来非常灵活和干净。干杯!