管道简介
Nest.js 的管道(Pipes)用于处理输入数据的转换和验证。可以执行以下任务:
- 验证(Validation):确保传入请求的数据符合某些标准,如果数据无效,则可以抛出异常。
- 转换(Transformation):将输入数据转换成期望的形式,例如从字符串转换成整数,或者从用户输入的日期字符串转换为 Date 对象。
管道有两种类型:
- 内置管道 :Nest.js 提供了一些内置的管道,例如
ValidationPipe
、ParseIntPipe
等。 - 自定义管道:用户可以创建自定义管道来满足特定的需求。
我们先来介绍内置管道。
内置管道
Nest 内置的 Pipe:
- ValidationPipe
- ParseIntPipe
- ParseBoolPipe
- ParseArrayPipe
- ParseUUIDPipe
- DefaultValuePipe
- ParseEnumPipe
- ParseFloatPipe
- ParseFilePipe
创建项目:
bash
nest new pipe-test -p npm
ParseIntPipe
ParseIntPipe
转换参数为整数,无法转换或者转换后不是整数则抛出异常:
访问页面可以看出 age 是字符串,因为字符串 + 数字才会拼接:
我们使用 ParseIntPipe
:
正确相加:
传递一个无法转换整数的会报错:
我们还可以自定义错误:
重新访问:
这里也可以通过 exceptionFactory 选项自定义异常工厂函数,抛出异常,让异常过滤器自己处理。
ParseFloatPipe
ParseFloatPipe
是将参数转换为浮点数:
访问下:
同样支持 new ParseFloatPipe 的形式,可传入 errorHttpStatusCode 和 exceptionFactory 选项自定义错误。
ParseBoolPipe
ParseBoolPipe
用于将输入的字符串转换为布尔值。如果输入的值无法转换为布尔值,则会抛出异常。
ParseEnumPipe
ParseEnumPipe
用于确保输入的值是特定枚举中的一个有效值。如果输入的值不在枚举中,则会抛出异常。
如果 role 的值不是 admin 或 user,则会抛出 BadRequestException。
也同样可以通过 errorHttpStatusCode 和 exceptionFactory 来自定义错误。
ParseUUIDPipe
ParseUUIDPipe 用于验证输入的字符串是否是有效的 UUID(通用唯一标识符)。如果不是有效的 UUID,则会抛出异常。
我们用 uuid 包可以生成 uuid:
DefaultValuePipe
DefaultValuePipe 用于为参数提供一个默认值:
ParseArrayPipe
用于将客户端发送的字符串数组解析为实际的数组类型:
先安装 class-validator 包,这是可以用装饰器和非装饰器两种方式对 class 属性做验证的库。
再安装 class-transformer 包,它是把普通对象转换为对应的 class 实例的包。
bash
npm install class-validator class-transformer -D
还剩下 ValidationPipe 和 ParseFilePipe,之后再讲。
使用管道的 4 种方式
管道不仅支持对某个参数级别生效,也能对整个 Controller 、方法、全局都生效。
typescript
// 参数级别的 Pipes
@Get(':id')
getUserById(@Param('id', ParseIntPipe) id: number) {
// ...
}
// Controller 生效
@Controller('users')
@UsePipes(ValidationPipe)
export class UsersController {
// ...
}
// 方法级别的 Pipes
@Controller('users')
export class UsersController {
@Post()
@UsePipes(ValidationPipe)
createUser(@Body() createUserDto: CreateUserDto) {
// ...
}
}
// 全局 Pipes
import { Module } from '@nestjs/common';
import { APP_PIPE } from '@nestjs/core';
import { ValidationPipe } from './pipes/validation.pipe';
@Module({
providers: [
{
provide: APP_PIPE,
useClass: ValidationPipe,
},
],
})
export class AppModule {}
创建自定义管道
创建自定义管道,需要实现 PipeTransform
接口,并定义 transform
方法。
下面管道,它将输入字符串转换为整数:
typescript
import { PipeTransform, Injectable, ArgumentMetadata, BadRequestException } from '@nestjs/common';
@Injectable()
export class ParseIntPipe implements PipeTransform<string, number> {
transform(value: string, metadata: ArgumentMetadata): number {
const val = parseInt(value, 10);
if (isNaN(val)) {
throw new BadRequestException('Validation failed');
}
return val;
}
}
使用这个自定义管道:
typescript
import { Controller, Get, Query, UsePipes } from '@nestjs/common';
import { ParseIntPipe } from './parse-int.pipe';
@Controller('numbers')
export class NumbersController {
@Get()
@UsePipes(ParseIntPipe)
async getNumber(@Query('num') num: number): Promise<number> {
// num 参数已经被 ParseIntPipe 转换为整数
return num;
}
}
当客户端发起请求并传递 num
查询参数时,ParseIntPipe
会自动将 num
转换为整数类型,然后传递给 getNumber
方法。