我有HeroMockService个将返回模拟数据,还有HeroService个将调用后端服务从数据库中检索英雄.

假设Angular2有构建环境,如果当前构建环境是"dev-mock",我计划注入HeroMockServiceAppComponent.如果当前构建环境是"dev-rest",则应改为将HeroService注入AppComponent.

我想知道怎样才能做到这一点呢?

推荐答案

在国际海事组织,更好的 Select 是使用angular-in-memory-web-api.

这个项目从its old location个拉到了angular/angular个.

它模拟Http使用的后端,因此它不进行实际的XHR调用,而只是获取您提供给它的数据.要获得它,只需安装

npm install --save angular-in-memory-web-api

要创建数据库,需要在InMemoryDbService中实现createDb方法

import { InMemoryDbService } from 'angular-in-memory-web-api'

export class MockData implements InMemoryDbService {
  let cats = [
    { id: 1, name: 'Fluffy' },
    { id: 2, name: 'Snowball' },
    { id: 3, name: 'Heithcliff' },
  ];
  let dogs = [
    { id: 1, name: 'Clifford' },
    { id: 2, name: 'Beethoven' },
    { id: 3, name: 'Scooby' },
  ];
  return { cats, dogs, birds };
}

然后配置它

import { InMemoryWebApiModule } from 'angular-in-memory-web-api';

@NgModule({
  imports: [
    HttpModule,
    InMemoryWebApiModule.forRoot(MockData, {
      passThruUnknownUrl: true
    }),
  ]
})

现在,当您使用Http并向/api/cats发出请求时,它将从数据库中获取所有的cat .如果你到/api/cats/1,它会得到第一只cat .您可以执行所有CRUD操作,GET、POST、PUT、DELETE.

需要注意的一点是,它需要一个基本路径.在示例中,/api是基本路径.您还可以在配置中配置根路径(这与基本路径不同)

InMemoryWebApiModule.forRoot(MockData, {
  rootPath: 'root',
  passThruUnknownUrl: true // forwards request not in the db
})

现在你可以使用/root/api/cats.


更新

关于如何从开发切换到生产的问题,您可以使用工厂来创建提供者.如果您使用模拟服务而不是内存中的web api,情况也是如此

providers: [
  Any,
  Dependencies
  {
    // Just inject `HeroService` everywhere, and depending
    // on the environment, the correct on will be chosen
    provide: HeroService, 
    useFactory: (any: Any, dependencies: Dependencies) => {
      if (environment.production) {
        return new HeroService(any, dependencies);
      } else {
        return new MockHeroService(any, dependencies);
      }
    },
    deps: [ Any, Dependencies ]
]

至于内存中的web api,我需要回复您(我需要测试一个理论).我刚开始使用它,还没有到需要切换到生产的地步.现在我只有上面的配置.但我相信有一种方法可以让它在不改变任何东西的情况下工作

更新2

好的,对于im-memory-web-API,我们可以做的不是导入模块,而是只提供模块提供的XHRBackend.XHRBackendHttp用来进行XHR呼叫的服务.内存中的WEP-API模拟该服务.这就是模块所做的全部工作.所以我们可以自己提供服务,用一家工厂

@NgModule({
  imports: [ HttpModule ],
  providers: [
    {
      provide: XHRBackend,
      useFactory: (injector: Injector, browser: BrowserXhr,
                   xsrf: XSRFStrategy, options: ResponseOptions): any => {
        if (environment.production) {
          return new XHRBackend(browser, options, xsrf);
        } else {
          return new InMemoryBackendService(injector, new MockData(), {
            // This is the configuration options
          });
        }
      },
      deps: [ Injector, BrowserXhr, XSRFStrategy, ResponseOptions ]
    }
  ]
})
export class AppHttpModule {
}

请注意BrowserXhrXSRFStrategyResponseOptions依赖项.原版XHRBackend就是这样制作的.现在,不要将HttpModule导入应用程序模块,只需导入AppHttpModule即可.

至于environment,这是你需要弄清楚的.使用angular cli,当我们在生产模式下构建时,环境已经自动切换到生产环境.

下面是我用来测试的完整示例

import { NgModule, Injector } from '@angular/core';
import { HttpModule, XHRBackend, BrowserXhr,
         ResponseOptions,  XSRFStrategy } from '@angular/http';

import { InMemoryBackendService, InMemoryDbService } from 'angular-in-memory-web-api';

let environment = {
  production: true
};

export class MockData implements InMemoryDbService {
  createDb() {
    let cats = [
      { id: 1, name: 'Fluffy' }
    ];
    return { cats };
  }
}

@NgModule({
  imports: [ HttpModule ],
  providers: [
    {
      provide: XHRBackend,
      useFactory: (injector: Injector, browser: BrowserXhr,
                   xsrf: XSRFStrategy, options: ResponseOptions): any => {
        if (environment.production) {
          return new XHRBackend(browser, options, xsrf);
        } else {
          return new InMemoryBackendService(injector, new MockData(), {});
        }
      },
      deps: [ Injector, BrowserXhr, XSRFStrategy, ResponseOptions ]
    }
  ]
})
export class AppHttpModule {
}

Angular相关问答推荐

FormArray包含嵌套的FormGroups.如何访问嵌套的表单组控件?

垫-菜单未以17.2.3角显示

带逻辑的组件decorator 中的Angular 主机侦听器属性

对子router-outlet 应用主机样式

Rxjs重置执行后的可观察延迟并重新调度Angular

仅在展示时使用垫式步进器

以Angular 动态添加和删除组件形状元素

Angular 如何观察DOM元素属性的变化?

无法匹配任何路由.URL段:';英雄';

元素上的Angular 管道链接不起作用

根据环境变量动态加载Angular templateUrl

Angular 路由中的模块构建失败

根据最后发出的 observable 创建一个 observable

检测父元素是否绑定到 Angular 中的子元素 @Output

Angular:将间隔与增量和减量相结合

rxjs 这种常见的状态管理模式有名称吗?它有限制吗?

使用 Angular2 将文件上传到 REST API

相对于根目录的 SCSS 导入

如何导航到同级路由?

RxJS - 发生错误时观察到的不会完成