nestjs笔记
控制反转 IoC
控制反转(Inversion of Control,缩写为 IoC)是面向对象编程中的一种设计原则,可以用来降低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
网关
import { NestFactory } from '@nestjs/core';
import {
FastifyAdapter,
NestFastifyApplication,
} from '@nestjs/platform-fastify';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter(),
);
await app.listen(3000);
}
bootstrap();
版本控制
单个请求控制
// main.ts. 接口版本化管理
app.enableVersioning({
type: VersioningType.URI,
});
// 在Controller中
import { Controller, Version } from '@nestjs/common';
@Get()
@Version('1') // add this line
findAll() {
return this.userService.findAll();
}
多版本控制
// 全局配置请求控制
全局参数返回
统一响应体格式
全局异常拦截
base 异常
http异常
处理业务异常
环境配置
swager 文档配置
对接飞书 环境参数 alias配置
请求封装
参数校验 约束前端传参数
使用 class-validator 内置的验证装饰器对需要验证的 Dto 参数添加校验。
import { RECEIVE_TYPE, MSG_TYPE } from '@/helper/feishu/message';
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsEnum } from 'class-validator';
export class FeishuMessageDto {
@IsNotEmpty()
@IsEnum(RECEIVE_TYPE)
@ApiProperty({ example: 'email' })
receive_id_type: RECEIVE_TYPE
@IsNotEmpty()
@ApiProperty({ example: 'cookieboty@qq.com' })
receive_id?: string
@IsNotEmpty()
@ApiProperty({ example: '{\"text\":\" test content\"}' })
content?: string
@IsNotEmpty()
@IsEnum(MSG_TYPE)
@ApiProperty({ example: 'text' })
msg_type?: MSG_TYPE
}
我们使用了 IsNotEmpty(禁止传空)以及 IsEnum(参数必须是有效的枚举)来约束前端传参数
装饰器 描述
常见的验证装饰器
@IsDefined(value: any) 检查值是否已定义(!== undefined, !== null)。这是唯一忽略 skipMissingProperties 选项的装饰器。
@IsOptional() 检查给定值是否为空(=== null,=== undefined),如果是,则忽略该属性上的所有验证器。
@Equals(comparison: any) 检查值是否等于 (“=“) 比较。
@NotEquals(comparison: any) 检查值是否不等于 (”!”) 比较。
@IsEmpty() 检查给定值是否为空(=== ‘’、=== null、=== 未定义)。
@IsNotEmpty() 检查给定值是否不为空(!== ‘’,!== null,!== undefined)。
@IsIn(values: any[]) 检查值是否在允许值的数组中。
@IsNotIn(values: any[]) 检查 value 是否不在不允许的值数组中。
类型验证装饰器
@IsBoolean() 检查值是否为布尔值。
@IsDate() 检查值是否为日期。
@IsString() 检查字符串是否为字符串。
@IsNumber(options: IsNumberOptions) 检查值是否为数字。
@IsInt() 检查值是否为整数。
@IsArray() 检查值是否为数组
@IsEnum(entity: object) 检查值是否是有效的枚举
完成了参数校验后,还剩下最后一步,先看下现在的文档描述。
image.png
从上述页面中可以看出,接口字段描述使用 enum 类型在展示上并不直观,对接的前端同学无法感知到底用了什么、需要传什么值才能符合要求,这个可以使用 Swagger 中 ApiProperty 的 enum 参数,来让文档识别出对应的枚举参数:
QS
nestjs怎么检索SetMetadata设置的元数据
在 NestJS 中,可以使用 Reflector 类来检索通过 @SetMetadata 装饰器设置的元数据。以下是一个简单的示例:
import { Controller, Get, SetMetadata } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
// SetMetadata会返回一个
const Roles = (...roles: string[]) => SetMetadata('roles', roles);
@Controller('cats')
export class CatsController {
constructor(private readonly reflector: Reflector) {}
@Roles('admin')
@Get()
findAll() {
const roles = this.reflector.get<string[]>('roles', this.findAll);
console.log(roles); // ['admin']
return 'This action returns all cats';
}
}
在上面的示例中,@Roles(‘admin’) 装饰器使用 SetMetadata 来设置 roles 元数据。然后,我们在 findAll 方法中使用 Reflector 类的 get 方法来检索该元数据。该方法需要两个参数:要检索的元数据的键(这里是 ‘roles’)和装饰器所应用的目标对象(这里是 this.findAll,即 findAll 方法本身)。该方法返回一个包含元数据的数组(在本例中是 [‘admin’])。
####### ts是怎么实现元数据的
在 TypeScript 中,元数据是通过装饰器来实现的。装饰器是一种特殊类型的声明,可以附加到类声明、方法、属性或参数上,以修改类的行为。装饰器使用 @ 符号后跟一个表达式,并将其放置在要修饰的声明之前。
装饰器可以用来添加元数据,例如类型信息、注解和其他标记。这些元数据可以在运行时使用,以便执行特定操作。例如,Express 框架使用装饰器来定义路由处理程序,并从中构建路由表。
要访问元数据,可以使用 Reflect API 中的 reflect-metadata 库。该库提供了一组函数,可用于获取和设置元数据。例如,可以使用 reflect-metadata 库获取类的元数据:
import 'reflect-metadata';
class MyClass {
// Define metadata for this class
}
const metadata = Reflect.getMetadata('myMetadataKey', MyClass);
在上面的示例中,我们使用 Reflect.getMetadata() 函数从 MyClass 中获取名为 ‘myMetadataKey’ 的元数据。
nestjs的Providers有什么用
在 NestJS 中,Providers 是一种特殊类型的类,用于管理应用程序中的依赖注入(Dependency Injection,DI)系统。简单来说,Provider 的作用就是将各个模块或组件的不同部分联系起来,使它们能够互相协作并实现功能。
在 NestJS 中,Providers 可以用于以下方面:
依赖注入:在应用程序中,Providers 可以被用来实现依赖注入(Dependency Injection,DI)。通过 DI,我们可以轻松地管理应用程序中的依赖关系,并使不同的组件之间相互独立。
单例模式:在 NestJS 中,Provider 通常是单例模式,这意味着我们可以将它们用来保存应用程序的全局状态。因为 Provider 只会被实例化一次,所以我们可以在不同的组件之间共享相同的数据。
模块管理:在 NestJS 中,Provider 通常是模块的一部分。这意味着我们可以将不同的 Provider 分组到不同的模块中,并在需要时轻松地加载它们。
可重用性:在 NestJS 中,Provider 可以轻松地重用,这意味着我们可以在不同的应用程序中使用相同的 Provider,从而提高代码的可维护性和可重用性。
总之,Provider 是 NestJS 中非常重要的概念之一,它使我们能够轻松地管理应用程序的依赖关系,并实现各种复杂的功能。
那nestjs的提供者和ts的装饰器有什么区别
NestJS提供者和TypeScript装饰器的作用是不同的。
TypeScript装饰器是一种语法糖,可以为类、属性、方法等添加元数据,以及在运行时修改它们的行为。而NestJS提供者是一种特殊类型的装饰器,它用于将一个类注入到应用程序中。
具体来说,NestJS提供者是一种特殊类型的类,它使用依赖注入(DI)机制在整个应用程序中共享实例。这些提供者被注入到控制器、服务或其他提供者中,以便在应用程序中实现组件的重用和松散耦合。
因此,尽管两者都使用装饰器语法,但它们的作用和使用方式是不同的。
用nestjs读取mp4文件并且给这个虎牙推流的demo
这个地址是一个RTMP协议的流媒体地址,它的主机名为"hs.direct.huya.com",RTMP是一种实时音视频流传输协议,常用于直播和视频会议等场景。
如果想用NestJS编写一个读取MP4文件并推流的demo,需要使用Node.js的流处理功能以及RTMP推流库。以下是实现这个demo的大致思路:
- 安装相关依赖库,比如fluent-ffmpeg、node-media-server等;
- 使用fluent-ffmpeg读取MP4文件,将其转为可被RTMP推流库处理的视频流;
- 创建一个RTMP服务器实例,并监听客户端的连接请求;
- 当有客户端连接到服务器时,将视频流推送给客户端。
下面是一个基本的示例代码:
import { Controller, Get } from '@nestjs/common';
import * as fs from 'fs';
import * as path from 'path';
import * as ffmpeg from 'fluent-ffmpeg';
import * as NodeMediaServer from 'node-media-server';
@Controller()
export class AppController {
@Get()
async stream() {
const videoPath = path.join(__dirname, 'video.mp4');
const stat = fs.statSync(videoPath);
const fileSize = stat.size;
const nms = new NodeMediaServer({
rtmp: {
port: 1935,
chunk_size: 60000,
gop_cache: true,
ping: 60,
ping_timeout: 30,
},
});
nms.on('prePublish', (id, streamPath, args) => {
console.log('[NodeEvent on prePublish]', `id=${id} streamPath=${streamPath} args=${JSON.stringify(args)}`);
const stream = fs.createReadStream(videoPath);
const avconv = new ffmpeg();
avconv.input(stream)
.inputFormat('mp4')
.outputOptions('-c:v libx264')
.outputOptions('-preset veryfast')
.outputOptions('-tune zerolatency')
.outputOptions('-profile:v baseline')
.outputOptions('-level 3.0')
.outputOptions('-b:v 300k')
.outputOptions('-bufsize 600k')
.outputOptions('-maxrate 400k')
.outputOptions('-payload_type 99')
.outputOptions('-f flv')
.output(`rtmp://hs.direct.huya.com${streamPath}`);
avconv.run();
});
await nms.run();
}
}
在上面的示例代码中,我们首先通过fs模块读取了video.mp4文件,并获取了文件的大小。然后我们创建了一个NodeMediaServer实例,并配置了RTMP服务器的参数。
当有客户端连接到服务器时,我们通过fluent-ffmpeg将video.mp4文件转为可被RTMP推流库处理的视频流,并使用RTMP推流库将视频流推送给客户端。
这只是一个简单的示例,实际的应用可能需要更多的功能,比如授权、流控、转码、水印等。但是这个示例可以帮助你了解如何使用NestJS和Node.js的流处理功能来实现一个基本的RT