Nestjs入门系列-03-Provides

107 阅读3分钟

提供者

高屋建瓴

我画了关于Nest最重要的三个概念(controllers,provides,modules)的流程图

Untitled.png

目前我们已经学习了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
  }
}

接下来我们来测试一下,添加两个小猫

Untitled 1.png

自定义提供者

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
  }
}

Untitled 2.png

由于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()
  }
}

Untitled 3.png

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 {}

原文链接codertao.notion.site/b9395a460a5…