接前一篇文章,我们在person.service.ts中我们使用了抽象类作为两个具体实现类的父类,但是用抽象类总感觉没有接口更合适,今天看看如果使用接口应该怎么使用useFactory,看下面列子
person.module.ts
export interface Person {
id: number;
name: string;
email: string;
}
person.service.ts
import { Injectable } from '@nestjs/common';
import { Person } from './person';
export interface PersonService {
findAll(): Promise<Person[]> ;
findOne(id: number): Promise<Person> ;
}
export class RealPersonService implements PersonService {
persons: Person[] = [];
constructor() {
this.persons = [
{ id: 1, name: 'John.real', email: 'john@example.com' },
{ id: 2, name: 'Jane.real', email: 'jane@example.com' },
{ id: 3, name: 'Bob.real', email: 'bob@example.com' },
];
}
async findAll(): Promise<Person[]> {
return this.persons;
}
async findOne(id: number): Promise<Person> {
const persons = this.persons.filter((person) => person.id == id);
return persons[0];
}
}
export class MockPersonService implements PersonService {
persons: Person[] = [];
constructor() {
this.persons = [
{ id: 1, name: 'John.mock', email: 'john@example.com' },
{ id: 2, name: 'Jane.mock', email: 'jane@example.com' },
{ id: 3, name: 'Bob.mock', email: 'bob@example.com' },
];
}
async findAll(): Promise<Person[]> {
return this.persons;
}
async findOne(id: number): Promise<Person> {
const persons = this.persons.filter((person) => person.id == id);
return persons[0];
}
}
@Injectable()
export class EnvUtils {
isDevelopment() {
return process.env.NODE_ENV === 'development';
}
isProduction() {
return process.env.NODE_ENV === 'production';
}
}
- 这里接口PersonService定义了要提供的方法;
- 另外提供了两个实例类,一个real实现,一个mock实现,为了简单只是修改其中person.name的值;
- 这里还定义了一个工具类,用来获取环境变量,判断运行场景;
person.controller.ts
import {
Controller,
Get,
Param,
Inject
} from '@nestjs/common';
import { Person } from './person';
import { PersonService } from './person.service';
@Controller('persons')
export class PersonController {
@Inject('PersonService')
private personService: PersonService;
@Get()
async findAll(): Promise<Person[]> {
return this.personService.findAll();
}
@Get(':id')
async findOne(@Param('id') id: number): Promise<Person> {
return this.personService.findOne(id);
}
}
- 这里注意一下没有使用构造函数注入,而是使用了属性注入;
person.module.ts
import { Inject, Module } from '@nestjs/common';
import { PersonController } from './person.controller';
import { PersonService, RealPersonService, MockPersonService, EnvUtils } from './person.service'
const PersonServiceProvider = {
provide: 'PersonService',
useFactory: (envUtils: EnvUtils) => {
if (envUtils.isDevelopment()) return new MockPersonService();
else if(envUtils.isProduction()) new RealPersonService();
else return new MockPersonService(); //throw new Error('Invalid environment');
},
inject: [EnvUtils]
}
@Module({
controllers: [PersonController],
providers: [PersonServiceProvider, EnvUtils],
})
export class PersonModule {}
- module类定义了一个PersonServiceProvider,其中使用useFactory来根据环境变量来决定使用具体那个PersonService的实现类;
- provide使用的是字符串而不是类;
- 作为列子,这里useFactory也依赖了一个注入对象,此时可以使用inject注入进来;
测试
export NODE_ENV=development && npm run start:dev
或者
export NODE_ENV=production && npm run start:dev