我有HeroMockService
个将返回模拟数据,还有HeroService
个将调用后端服务从数据库中检索英雄.
假设Angular2有构建环境,如果当前构建环境是"dev-mock"
,我计划注入HeroMockService
到AppComponent
.如果当前构建环境是"dev-rest"
,则应改为将HeroService
注入AppComponent
.
我想知道怎样才能做到这一点呢?
我有HeroMockService
个将返回模拟数据,还有HeroService
个将调用后端服务从数据库中检索英雄.
假设Angular2有构建环境,如果当前构建环境是"dev-mock"
,我计划注入HeroMockService
到AppComponent
.如果当前构建环境是"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,我需要回复您(我需要测试一个理论).我刚开始使用它,还没有到需要切换到生产的地步.现在我只有上面的配置.但我相信有一种方法可以让它在不改变任何东西的情况下工作
好的,对于im-memory-web-API,我们可以做的不是导入模块,而是只提供模块提供的XHRBackend
.XHRBackend
是Http
用来进行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 {
}
请注意BrowserXhr
、XSRFStrategy
和ResponseOptions
依赖项.原版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 {
}