前言

ProvidersNest中的一个基本概念,许多Nest中定义的类都可以被视为一个Provider,比如:service、repository、factory、helper等,它们都可以通过constructor注入依赖关系,这就意味着类与类之间可以创建各种依赖关系,并且维护各个类之间依赖关系的工作将委托给Nest运行时系统。

Provider类(service)基本用法

前面几章我们通过nest-cli生成的代码中就包含有service

比如:

// nanjiu.service.ts
import { Injectable } from '@nestjs/common';
import { CreateNanjiuDto } from './dto/create-nanjiu.dto';
import { UpdateNanjiuDto } from './dto/update-nanjiu.dto'; @Injectable()
export class NanjiuService {
create(createNanjiuDto: CreateNanjiuDto) {
return 'This action is nanjiu post';
} findAll() {
return `This action returns all nanjiu`;
} findOne(id: number) {
return `This action returns a #${id} nanjiu`;
} update(id: number, updateNanjiuDto: UpdateNanjiuDto) {
return `This action updates a #${id} nanjiu`;
} remove(id: number) {
return `This action removes a #${id} nanjiu`;
}
}

使用步骤如下:

@Injectable()装饰器

这里的NanjiuService类通过@Injectable装饰器标记为一个provider,表明该类可以被NestIOC容器管理

在module中注册

服务需要在对应的module中进行注册,如果不注册IOC容器是不会帮你创建对象的,而且还会报错

// nanjiu.module.ts
@Module({
controllers: [NanjiuController],
providers: [NanjiuService]
})
export class NanjiuModule {}

在controller中注入并使用

module中注册service类后,再通过controller的构造函数进行注入,那么该类就可以在controller中去使用了

// nanjiu.controller.ts

@Controller('nanjiu')
export class NanjiuController {
constructor(private readonly nanjiuService: NanjiuService) {} @Post()
@Header('Cache-Control', 'none')
create(@Body() createNanjiuDto: CreateNanjiuDto) {
console.log('body', createNanjiuDto)
return this.nanjiuService.create(createNanjiuDto);
}
}

可以看到是通过类构造函数 constructor(private readonly nanjiuService: NanjiuService) {}这种方式来进行依赖注入的,Nest提供了IOC容器利用Typescript自带类型的特点自动创建对象的能力,注意这里是单例模式,如果该Service在其它地方也被用过,那么会在不会重新创建对象,各个应用只会有一个该Service的对象,容器会先寻找当前有没有,如果没有再进行创建。

自定义Provider

Provider可以是一个值(value),也可以是一个类(class),还可以是一个工厂函数(factory)

useClass

上面providers的那种写法其实是一种简写,它的完整写法应该是这样:

// nanjiu.module.ts
@Module({
controllers: [NanjiuController], // 控制器
providers: [{
provide: 'NANJIU', // 自定义依赖注入的标识
useClass: NanjiuService // 依赖注入的类
}]
})
export class NanjiuModule {}

完整写法可以通过provide属性给不同的provider标注不同的token

然后再controller中需要使用@Inject(对应的token)进行注入

// nanjiu.controller.ts
@Controller('nanjiu')
export class NanjiuController {
constructor(@Inject('NANJIU') private readonly nanjiuService: NanjiuService) {} @Post()
@Header('Cache-Control', 'none')
create(@Body() createNanjiuDto: CreateNanjiuDto) {
console.log('body', createNanjiuDto, this.nanjiuService)
return true
return this.nanjiuService.create(createNanjiuDto);
}
}

useValue

还可以使用useValue自定义注入值

// nanjiu.module.ts
@Module({ // 模块装饰器
controllers: [NanjiuController], // 控制器
providers: [{
provide: 'NANJIU', // 自定义依赖注入的标识
useValue: {
name: 'nanjiu' // 依赖注入的值
}
}]
})

useFactory

工厂函数可以提供动态的provider,由factory函数的返回值来确定,factory函数可以很简单也可以很复杂,它也可以使用其它provider,不过需要在inject属性进行注入,注入的provider可以是可选的

  • 工厂函数可以接受(可选)参数。

  • (可选)inject属性接受一组提供程序,Nest 将在实例化过程中解析这些提供程序并将其作为参数传递给工厂函数。这两个列表应该是相关的:Nest 将以inject相同的顺序将列表中的实例作为参数传递给工厂函数。

// nanjiu.module.ts
import { Module } from '@nestjs/common';
import { NanjiuService } from './nanjiu.service';
import { UserService } from 'src/user/user.service';
import { NanjiuController } from './nanjiu.controller'; @Module({ // 模块装饰器
controllers: [NanjiuController], // 控制器
providers: [{
provide: 'NANJIU', // 自定义依赖注入的标识
useClass: NanjiuService // 依赖注入的类
},
UserService,
{
provide: 'USER', // 自定义依赖注入的标识
useFactory: (...args) => { // 工厂模式
console.log('useFactory', args)
return new UserService() // 依赖注入的类
},
inject: [UserService] // 依赖注入的类
} ]
})
export class NanjiuModule {}

可选的Provider

有时你可能存在不一定需要解决的依赖关系。例如,你的类可能依赖于配置对象,但如果没有传递任何内容,则应使用默认值。在这种情况下,依赖关系变得可选,这时候可以给对应的注入服务再增加一个@Optional()装饰器就行

import { Injectable, Optional, Inject } from '@nestjs/common';

@Injectable()
export class HttpService<T> {
constructor(@Optional() @Inject('HTTP_OPTIONS') private httpClient: T) {}
}

异步Provider

useFactory可以返回一个promise 或者其他异步操作,Nest 将在实例化任何依赖(注入)此类提供程序的类之前等待promise的结果。

// nanjiu.module.ts
@Module({ // 模块装饰器
controllers: [NanjiuController], // 控制器
providers: [
UserService,
{
provide: 'USER', // 自定义依赖注入的标识
useFactory: async () => { // 工厂模式
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(new UserService())
}, 1000)
})
},
inject: [UserService] // 依赖注入的类
} ]
})
export class NanjiuModule {}

【NestJS系列】核心概念:Providers提供者的更多相关文章

  1. Spark系列-核心概念

    Spark系列-初体验(数据准备篇) Spark系列-核心概念 一. Spark核心概念 Master,也就是架构图中的Cluster Manager.Spark的Master和Workder节点分别 ...

  2. ZooKeeper 系列(一)—— ZooKeeper核心概念详解

    一.Zookeeper简介 二.Zookeeper设计目标 三.核心概念         3.1 集群角色         3.2 会话         3.3 数据节点         3.4 节点 ...

  3. ZooKeeper系列(一)—— ZooKeeper 简介及核心概念

    一.Zookeeper简介 Zookeeper 是一个开源的分布式协调服务,目前由 Apache 进行维护.Zookeeper 可以用于实现分布式系统中常见的发布/订阅.负载均衡.命令服务.分布式协调 ...

  4. Storm 系列(二)—— Storm 核心概念详解

    一.Storm核心概念 1.1 Topologies(拓扑) 一个完整的 Storm 流处理程序被称为 Storm topology(拓扑).它是一个是由 Spouts 和 Bolts 通过 Stre ...

  5. 框架源码系列十:Spring AOP(AOP的核心概念回顾、Spring中AOP的用法、Spring AOP 源码学习)

    一.AOP的核心概念回顾 https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/core.html#a ...

  6. dubbo入门学习(一)-----分布式基础理论、架构发展以及rpc、dubbo核心概念

    一.分布式基础理论 1.什么是分布式系统? <分布式系统原理与范型>定义: “分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像单个相关系统” 分布式系统(distributed ...

  7. [程序设计语言]-[核心概念]-02:名字、作用域和约束(Bindings)

    本系列导航 本系列其他文章目录请戳这里. 1.名字.约束时间(Binding Time) 在本篇博文开始前先介绍两个约定:第一个是“对象”,除非在介绍面向对象语言时,本系列中出现的对象均是指任何可以有 ...

  8. Redux 核心概念

    http://gaearon.github.io/redux/index.html ,文档在 http://rackt.github.io/redux/index.html .本文不是官方文档的翻译. ...

  9. SpaceSyntax【空间句法】之DepthMapX学习:第二篇 输出了什么东西 与 核心概念

    这节比较枯燥,都是原理,不过也有干货.这篇能不能听懂,就决定是否入门...所以,加油吧 博客园/B站/知乎/CSDN  @秋意正寒 转载请在文头注明本文地址 本篇讲空间句法的几个核心概念,有一些也是重 ...

  10. Eureka中的核心概念

    图片的链接出了一点小bug,导致图片不能正常访问,小伙伴们可以移步这里:https://mp.weixin.qq.com/s/kAqOTKUt_qPlxzI4aGS5Pw 本文是Spring Clou ...

随机推荐

  1. Qt+MySql开发笔记:Qt5.9.3的msvc2017x64版本编译MySql8.0.16版本驱动并Demo连接数据库测试

    前言   mysql驱动版本msvc2015x32版本调好, mysql的mingw32版本的驱动上一个版本编译并测试好,有些三方库最低支持vs2017,所以只能使用msvc2017x64,基于Qt5 ...

  2. Vue中实现数据列表无缝轮播

    类似这种滚动轮播效果 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta char ...

  3. Godot 4.0 文件读取(C#)

    搞半天才弄明白Godot文件操作. Godot的文档总是试图让我使用自定义Resource来支持文件操作,但是我只需要读取纯文本. 读取纯文本 读取纯文本的方式如下: //Godot.FileAcce ...

  4. OceanBase的学习与使用

    OceanBase的学习与使用 简介 1. OceanBase数据库 注意这一块下载的其实是rpm包. 一般是通过下面的OAT或者是OCP工具进行安装. 有x86还有ARM两种架构. 虽然是el7结尾 ...

  5. RestTemplate发送get请求并携带请求头

    //设置请求头 HttpHeaders headers = new HttpHeaders(); headers.add("X-Access-Token", huaWenToken ...

  6. 2022-04-29:厨房里总共有 n 个橘子,你决定每一天选择如下方式之一吃这些橘子: 吃掉一个橘子。 如果剩余橘子数 n 能被 2 整除,那么你可以吃掉 n/2 个橘子。 如果剩余橘子数 n 能被

    2022-04-29:厨房里总共有 n 个橘子,你决定每一天选择如下方式之一吃这些橘子: 吃掉一个橘子. 如果剩余橘子数 n 能被 2 整除,那么你可以吃掉 n/2 个橘子. 如果剩余橘子数 n 能被 ...

  7. 2021-06-21:贩卖机只支持硬币支付,且收退都只支持10 ,50,100三种面额。一次购买只能出一瓶可乐,且投钱和找零都遵循优先使用大钱的原则,需要购买的可乐数量是m, 其中手头拥有的10、50

    2021-06-21:贩卖机只支持硬币支付,且收退都只支持10 ,50,100三种面额.一次购买只能出一瓶可乐,且投钱和找零都遵循优先使用大钱的原则,需要购买的可乐数量是m, 其中手头拥有的10.50 ...

  8. nodejs 中 stream.pipe()直接将文件输出到页面乱码

    最近仿照anywhere写个anyentry目录读取器,发现使用stream.pipe()将文件输入到页面时,出现中文乱码 看哇 看到着实不爽,不解决咋能算 于是开始寻找问题根源 一.配置encodi ...

  9. \n被当成回车处理

    Regex.Escape   C# 字符串变量str 的值为"a\nb"如果直接输出显示的话,就成了:ab需要输出显示为:a\nb string str = "a\nb& ...

  10. R 语言主成分分析(PCA)实战教程

    作者:落痕的寒假原文:https://blog.csdn.net/LuohenYJ/article/details/97950522 声明:本文章经原作者同意后授权转载. 主成分分析 Principa ...