自定义装饰器
简单使用
当 Nest 内置的装饰器不能满足开发需求时,可以自定义装饰器,其自定义装饰器的规则和 react 的自定义 hooks 较为相似,自定义时,其封装必须使用 Nest 的内置装饰器或者其它自定义装饰器,react 中是必须使用 react hooks,这一点规则类似。
使用命令快速创建一个 decotator 模板
nest g decorator role --flat
这就是一个最基础的自定义装饰器,然后创建一个 guard 模板,使用 guard。
自定义装饰器调用其它装饰器
当装饰器相使用过多且相似时,可以在自定义装饰器里通过 applyDecorators
组合多个其它装饰器(包括其它的自定义装饰器)
applyDecorators
可以将多个装饰器合并条用
自定义参数装饰器
createParamDecorator
顾名思义,创建参数装饰器。可以接收装饰器传入的参数,还内置了 ctx 上下文,用于获取 request、response 等参数。
Module 和 Provider 循环依赖问题
什么是循环依赖,比如 A 模块引用了 B 模块,而 B 模块也引用了 A 模块,在执行时,IOC 容器就不知道该先注入A 还是先注入 B。这就是 Nest 中的循环引用。
注:Springboot 大于 2.7 版本之后,已经默认禁止了循环引用。
首先做一个相互引用的示例:
此时启动之后报错
报错的主要错误信息就是:模块之间的存在循环依赖。需使用 forwardRef()
来避免。可以阅读文档 循环依赖
Module 之间的互相导入
对于 Module 之间导入时的循环引用可以使用如下方式
Service 之间的互相注入
对于 Service 层的互相注入,在 @Inject
时,则同样需要添加 forwardRef()
,不然也会报错
总结
forwardRef
就是解决 Module 之间的互相导入,Service 之间的互相注入用的。其本质就是通过函数延迟解析,直到所有相关的模块都已被扫描并且注册到容器中。这样当函数被调用时,相关的模块已经可用,从而解决了循环依赖问题。
动态创建模块
provider 是可以通过 useFactory
动态生成数据的,详情可阅读 Nestjs基础(二)。Module 也是可以的。文档链接 动态模块
需要给 module 添加 register
静态方法,然后可以通过外部传入参数,在不同模块导入的时候,可以定义不同的数据
取值时,就还是使用 @Inject
注入
约定名称
动态模块的 register
方法并不是非要用此方法名,但 nest 约定了 3 种方法名,来分别用来做不同的事情
- register
- 用一次模块传一次配置,比如这次调用是
AModule.register({age:20})
,下一次就是BModule.register({aaa:2})
了
- 用一次模块传一次配置,比如这次调用是
- forRoot
- 配置一次模块用多次,比如
AModule.forRoot({age:20})
一次,之后就一直用这个 Module 配置,一般在 AppModule 里 import forRootAsync
就是在配置时,有异步操作,比如需要异步拿到服务配置,才能进行静态配置的生成
- 配置一次模块用多次,比如
- forFeature
- 使用了 forRoot 固定整体模块,用于局部的时候,可能需要再传一些配置,比如用 forRoot 指定了数据库链接信息,再用 forFeature 指定某个模块访问哪个数据库和表。