Nestjs系列 Nestjs进阶(一)
自定义装饰器
简单使用
当 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 指定某个模块访问哪个数据库和表。
Nest 与 Express Fastify 的关系和切换
Express 是一个轻量级处理请求、响应的库,其基本使用如下:
import bodyParser from 'body-parser';
import express from 'express';
import http from 'http';
import router from './router';
const app = express();
app.use(bodyParser.json());
router(app);
const server = http.createServer(app);
server.listen(8848, () => {
console.log('server running on http://localhost:8848');
});
// router.js
export default (app) => {
app.post('/list', async (req, res, next) => {
res.send({
code:200,
data:[]
});
});
};
但 Express 只是一个处理请求的库,并没有提供组织代码的架构能力,其处理能力也是由各种中间件支撑的,项目庞大之后,没有严格的代码架构规范是很难维护的。
目前 Node 服务有三种层次的架构
- 直接使用 http、https 的模块
- 使用 express、koa 这种库,koa 也可以算作企业级框架
- Nest 这种企业级框架
- Nest 的架构就类似于 java 中的 Springboot
Nest 并没有和 express 进行强绑定,只是做了一层抽象(通过自己封装的 HttpServer 的 interface )
