Skip to content

管道PIPE

向军大叔每晚八点在 抖音bilibli 直播

xj-small

管道pipe用于对控制器接收的数据进行验证或类型转换

内置管道

Nest 自带九个开箱即用的内置管道

  • ValidationPipe
  • ParseIntPipe
  • ParseFloatPipe
  • ParseBoolPipe
  • ParseArrayPipe
  • ParseUUIDPipe
  • ParseEnumPipe
  • DefaultValuePipe
  • ParseFilePipe

声明方式

管道可以使用以下方式声明使用

控制器

控制器

@UsePipes(ValidationPipe)
export class UserController{
}

控制器方法

@UsePipes(ValidationPipe)
show()

方法参数

show(@param('id',ParseIntPipe))

模块

一般用于声明对模块全局影响的管道如表单验证

...
import { ValidatePipe } from './validate.pipe';
import { APP_PIPE } from '@nestjs/core';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [
    AppService,
    {
      provide: APP_PIPE,
      useClass: ValidatePipe,
    },
  ],
})
export class AppModule {}

全局管道

一般用于声明对模块全局影响的管道如表单验证

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe());
  await app.listen(3000, '0.0.0.0');
}

类型转换

使用管道可以对请求数据进行转换

常规方式

以下代码将报错,因为 findUnique 需要数值类型

import { Controller, Get, Param } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}
  
  @Get(':id')
  show(@Param('id') id) {
    return this.appService.users.findUnique({
      where: { id },
    });
  }
}

我们可以改良下,将id强制转为数值

...
return this.appService.users.findUnique({
  where: { id: +id },
});
..

使用管道

不过使用 ParseIntPipe 管道操作更推荐,它是专门做数据转换的

show(@Param('id', ParseIntPipe) id) {
  return this.appService.users.findUnique({
    where: { id },
  });
}

也可以定义响应的状态码

@Get()
show(
  @Query(
    'id',
    new ParseIntPipe({
      errorHttpStatusCode: HttpStatus.BAD_REQUEST,
    }),
  )
  id: number,
) {
  return this.prisma.user.findUnique({
    where: {
      id,
    },
  });
}

也可以使用工厂函数自定义响应,下面是自定义响应消息

@Get()
show(
  @Query(
    'id',
    new ParseIntPipe({
      exceptionFactory: () => {
        throw new BadRequestException('请传递数字');
      },
    }),
  )
  id: number,
) {
  return this.prisma.user.findUnique({ where: { id } });
}

默认值管道

使用 DefaultValuePipe 管道用于定义默认值,下面示例表示,当没有 id 参数 时默认为1

@Get()
show(@Query('id', new DefaultValuePipe(1), ParseIntPipe) id: number) {
  return this.prisma.users.findUnique({
    where: { id },
  });
}

自定义管道

如果系统提供的管道不够使用,你也可以自定义管道。

自定义管道也非常简单,使用下面命令将创建管道 custom.pipe.ts 用于对数据进行数值转换,即实现 ParseIntPipe 管道。

nest g pi custom

管道内容如下

import { ArgumentMetadata, Injectable, PipeTransform } from '@nestjs/common';

@Injectable()
export class CustomPipe implements PipeTransform {
  transform(value: any, metadata: ArgumentMetadata) {
    return metadata.metatype == Number ? +value : value;
  }
}

下面以控制器方法 login(@Body('mobile', CustomPipe) mobile: number) 对metadata管道参数进行说明

选项说明
metatype参数类型:mobile:number ,metatype 为 number 构造函数
type参数类别: 如@Body、@Query
data参数名称:@Body('mobile',CustomPipe),data为mobile

然后就可以在控制器中使用管道了

import { Body, Controller, Post } from '@nestjs/common';
import { CustomPipe } from 'src/auth.pipe';
import { AuthService } from './auth.service';

@Controller()
export class AuthController {
  constructor(private readonly authService: AuthService) {}

  @Post()
  register() {
    return 'register';
  }

  @Post('login')
  login(@Body('mobile', CustomPipe) mobile: number) {
    return mobile;
  }
}