在NestJS中通常一个模块有如下结构
- person.module.ts - 定义模块类
- person.service.ts - 定义服务类
- person.controller.ts - 定义控制器类
- person.module.ts - 模块类
这里模块类 person.module.ts 大致有如下内容
import { Module } from '@nestjs/common';
import { PersonController } from './person.controller';
import { PersonService } from './person.service'
@Module({
imports: [],
controllers: [PersonController],
providers: [PersonService],
})
export class PersonModule {}
但是如果此时我们的service类有多个实现,具体使用哪个实现类需要根据环境来决定时,应该怎么处理呢?
此时我们就可以使用NestJS中provider的useClass来实现了,看下面例子:
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 abstract class PersonService {
abstract findAll(): Promise<Person[]> ;
abstract findOne(id: number): Promise<Person> ;
}
export class RealPersonService extends PersonService {
persons: Person[] = [];
constructor() {
super();
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 extends PersonService {
persons: Person[] = [];
constructor() {
super();
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];
}
}
- 这里抽象类PersonService定义了要提供的方法(这里之所以没有使用Interface是为了在module里配置的时候可以写类名,如果是Interface的话provider是不能写类的;
- 另外提供了两个实例类,一个real实现,一个mock实现,为了简单只是修改其中person.name的值;
person.controller.ts
import {
Controller,
Get,
Param,
} from '@nestjs/common';
import { Person } from './person';
import { PersonService } from './person.service';
@Controller('persons')
export class PersonController {
constructor(private readonly 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);
}
}
- 控制类简单注入了PersonService类;
person.module.ts
import { Module } from '@nestjs/common';
import { PersonController } from './person.controller';
import { PersonService, RealPersonService, MockPersonService } from './person.service'
const PersonServiceProvider = {
provide: PersonService,
useClass: process.env.NODE_ENV === 'development'
? MockPersonService
: RealPersonService,
}
@Module({
imports: [],
controllers: [PersonController],
providers: [PersonServiceProvider],
})
export class PersonModule {}
- module类定义了一个PersonServiceProvider,其中使用useClass来根据环境变量来决定使用具体那个PersonService的实现类;
测试
npm run start:dev
或者
export NODE_ENV=development && npm run start:dev