提供者
高屋建瓴
我画了关于Nest最重要的三个概念(controllers,provides,modules)的流程图
目前我们已经学习了controller,接下来我们学习provide
客人究竟想要什么(客户端需要获取什么),点好的菜给服务员(比如:我想要全部user的信息),然后服务员把客人点的那些菜报给厨师(比如/users Get),厨师拿到了菜单开始炒菜(provide里执行具体的业务逻辑:比如从数据库中筛选条件获取数据然后返回给controller),厨师抄完菜后通知服务员来端菜(provide里return data,controller获取到data),服务员把菜端给客人(controller返回data),最后客人进行食用(客户端获取到响应结果)
服务
让我们从创建一个简单的 CatsService开始。该服务将负责存储数据和返回数据,其由 CatsController使用,因此把它定义为 provider,是一个很好的选择
我们可以使用cli命令创建服务
nest g mo cats
nest g co cats --no-spec
nest g s cats --no-spec
// cats/cats.module.ts
import { Module } from '@nestjs/common'
import { CatsService } from './cats.service'
@Module({
providers: [CatsService],
})
export class CatsModule {}
// cats/cats/controller.ts
import { Body, Controller, Get, Post } from '@nestjs/common'
import { CatsService } from './cats.service'
import CatDto from './dto/cat.dto'
@Controller('cats')
export class CatsController {
constructor(private readonly cats: CatsService) {}
@Post()
createCat(@Body() cat: CatDto) {
this.cats.create(cat)
}
@Get()
findAllCats() {
return this.cats.findAll()
}
}
// cats/cats.service.ts
import { Injectable } from '@nestjs/common'
import CatDto from './dto/cat.dto'
@Injectable()
export class CatsService {
private readonly cats: CatDto[] = []
create(cat: CatDto) {
this.cats.push(cat)
}
findAll() {
return this.cats
}
}
接下来我们来测试一下,添加两个小猫
自定义提供者
NestJs也是支持我们自定义提供者的
useValue
我们也可以把普通数据通过useValue注入到provides里
// cats/cats.module.ts
import { Module } from '@nestjs/common'
import { CatsController } from './cats.controller'
import { organization } from './constant'
@Module({
controllers: [CatsController],
providers: [
{
// token(这里翻译为标记) -> 常量
provide: organization ,
useValue: 'ilun',
},
],
})
export class CatsModule {}
如果自定义provide使用一个字符串值的token的话需要使用@Inject进行注入
- 这个参数需要一个token值
// cats/cats/controller.ts
import { Controller, Get, Inject } from '@nestjs/common'
import { organization } from './constant'
@Controller('cats')
export class CatsController {
constructor(@Inject(organization) private readonly organization) {}
@Get('log')
log() {
return this.organization
}
}
由于TypeScript的结构类型,你可以使用任何具有兼容接口的对象,包括字面对象或用new实例化的类实例。
// cats/cats.module.ts
import { Module } from '@nestjs/common'
import { CatsController } from './cats.controller'
import { customClass } from './constant'
import CustomClass from './customClass'
@Module({
controllers: [CatsController],
providers: [
{
provide: customClass,
useValue: new CustomClass(),
},
],
})
export class CatsModule {}
// cats/cats/controller.ts
import { Controller, Get, Inject } from '@nestjs/common'
import { customClass } from './constant'
import CustomClass from './customClass'
@Controller('cats')
export class CatsController {
constructor(@Inject(customClass) private readonly custom: CustomClass) {}
@Get('custom')
log() {
return this.custom.log()
}
}
useClass
我们可以通过useClass使用普通的class或Service注册Provide
// cats/cats.module.ts
import { Module } from '@nestjs/common'
import { CatsController } from './cats.controller'
import { customClass } from './constant'
import CustomService from './custom.service'
import CustomClass from './customClass'
@Module({
controllers: [CatsController],
providers: [
{
provide: customClass,
useClass: CustomClass,
},
{
provide: CustomService,
useClass: CustomService,
},
],
})
export class CatsModule {}
// cats/cats/controller.ts
import { Controller, Get, Inject } from '@nestjs/common'
import { customClass } from './constant'
import CustomService from './custom.service'
import CustomClass from './customClass'
@Controller('cats')
export class CatsController {
constructor(@Inject(customClass) private readonly custom: CustomClass, private readonly customSer: CustomService) {}
@Get('custom')
log() {
return this.custom.log()
}
@Get('custom2')
log2() {
return this.customSer.log()
}
}
官网上举了一个例子,我们可以通过useClass来动态注册服务(类也可以)
这里我就简单演示一下,其实很简单就是读取配置然后进行判断
// cats/cats.module.ts
import { Module } from '@nestjs/common'
import { CatsController } from './cats.controller'
class DevelopmentConfigService {}
class ProductionConfigService {}
const configService = {
// 读取环境变量
provide: process.env.NODE_ENV === 'development' ? DevelopmentConfigService : ProductionConfigService,
useClass: process.env.NODE_ENV === 'development' ? DevelopmentConfigService : ProductionConfigService,
}
@Module({
controllers: [CatsController],
providers: [configService],
})
export class CatsModule {}
useFactory
针对于复杂要求的provider,我们可以使用 useFactory工厂函数对提供者进行注册
// cats/cats.module.ts
import { Module } from '@nestjs/common'
import { CatsController } from './cats.controller'
class aaa {
log() {
return 'aaa log'
}
}
const bbb = {
provide: 'bbb',
// 依赖注入其它的provide,将作为参数值传递给useFactory方法
inject: [aaaService],
useFactory: (options) => {
console.log(options.log()) // aaa log
},
}
@Module({
controllers: [CatsController],
providers: [aaa , bbb],
})
export class CatsModule {}