欢迎继续关注NestJs学习之旅系列文章管道熟悉Linux命令的小伙伴应该对“管道操作符”不陌生。ls-la|grep演示“|”是管道算子,将左边命令的输出作为右边命令的输入,支持级联。这样就可以通过pipelineoperator交替操作复杂的命令。NestJs中的管道也有类似的功能,也可以级联处理数据。NestJs管道使用@Injectable()装饰器进行装饰,需要实现PipeTransform接口。NestJs中pipeline的主要职责是:数据转换将输入数据转换为需要的输出数据,验证并接收客户端提交的参数,验证通过则继续传递,验证通过则提示错误fails执行顺序在上一篇文章中我们讨论了中间件、控制器、路由守卫之后,结合本题讨论的pipeline,可能有读者对这些组件的执行顺序有疑问:这些东西执行的顺序是什么?您不需要查找有关执行顺序的信息,只需在执行这些组件时添加日志即可。我得出了如下结论:客户端请求->中间件->路由守卫->管道->控制器方法开发管道数据转换类管道就不详细解释了:给你一个值和元数据,你的返回值就是转换后的价值。NestJs内置了ValidationPipe、ParseIntPipe和ParseUUIDPipe。为了更好地理解它们是如何工作的,我们以ValidationPipe(验证器管道)为例来演示管道的使用。PipeTransform这是管道必须实现的接口。接口定义如下:exportinterfacePipeTransform{transform(value:T,metadata:ArgumentMetadata):R;}value输入参数,T为输入参数类型元数据value的元数据,包括参数来源、参数类型等。输出参数,R为输出参数类型ArgumentMetadata用于描述当前处理值的元数据接口,接口定义如下:exportinterfaceArgumentMetadata{readonlytype:'身体'|'查询'|'参数'|'风俗';只读元类型?:类型<任何>;readonlydata?:string;}这个接口你可能看不懂,没关系,后面会有具体的例子解释。type输入数据的来源metatype>注入数据的类型data传递给装饰器的数据类型例如下面的控制器方法:@Post()login(@Query('type')type:number){//type为登录类型参数,类似电话号码login为1,账号login为2的例子}上例的元数据如下:typequery@Query装饰器读取GET参数metatypeNumbertypeTypesymboldatatype传递给@Query装饰器的参数为“type”validatorexample下面以用户登录时对账号密码的验证来说明validator管道的使用。规则如下:账号必须是字符串,长度为6-20个密码不能定义空的DTO。DTO是Java中的数据传输对象。简单的说,就是对数据进行一层包装。我们在NestJs中用这个东西来防止非法字段的提交和IDE自动提示(偷笑)。使用规则装饰器需要安装class-validator和class-transformer:npmi--saveclass-validatorclass-transformer登录表单定义如下://userLogin.dto.tsexportclassUserLoginDto{@IsString()@Length(6,20,{message:'长度不合法'})readonlyusername:string;@Length(1)readonlypassword:string;}管道定义因为我们的管道是通用的,也就是说验证什么内容是由外部决定的,管道只负责“你给我数据和规则,我来核实”。所以我们需要使用装饰器元数据。//validate.pipe.tsimport{ArgumentMetadata,BadRequestException,Injectable,PipeTransform}from'@nestjs/common';import{plainToClass}from'class-transformer';import{validate}from'class-validator';@Injectable()exportclassValidatePipeimplementsPipeTransform{asynctransform(value:any,{metatype}:ArgumentMetadata):Promise{if(!metatype||!this.toValidate(metatype)){//如果没有注入数据并且不需要验证,跳过处理返回值;}//数据格式转换constobject=plainToClass(metatype,value);//调用验证consterrors=awaitvalidate(object);//如果error的长度大于0,则证明错误,需要抛出400错误if(errors.length>0){thrownewBadRequestException(errors);}返回值;}/***要验证的数据类型*@parammetatype*/privatetoValidate(metatype:any):boolean{consttypes=[String,Boolean,Number,Array,Object];返回!types.includes(元类型);}}Controller定义今天的主角是pipeline,所以controller层不写逻辑//user.controller。ts@Post('登录')@UsePipes(ValidatePipe)login(@Body()userLoginDto:UserLoginDTO){return{errcode:0,errmsg:'ok'};}运行项目的项目根目录,执行如下命令运行NestJs项目:npmrun启动项目即可运行使用Postman验证:请求数据1{}响应数据1{"statusCode":400,"error":"BadRequest","message":[{"target":{},"property":"username","children":[],"constraints":{"length":"Invalidlength","isString":"usernamemustbeastring"}},{"target":{},"property":"password","children":[],"constraints":{"length":"密码必须大于等于1个字符"}}]}请求数据2{"username":"xialestudio"}响应数据2{"statusCode":400,"error":"BadRequest","message":[{"target":{"username":"xialeistudio"},"property":"password","children":[],"constraints":{"length":"密码必须大于等于1个字符"}}]}请求数据3{"username":"xialeistudio","password":"111111"}响应数据3[]注意事项以上演示了ValidatePipe的实现,生产环境可以直接使用NestJs提供的ValidationPipe,我们可以在main.ts中使用全局pipeline。create(AppModule);app.useGlobalPipes(newValidationPipe());awaitapp.listen(3000);}bootstrap();最后和笔者使用的SpringBoot中的验证框架对比后发现,实现的功能NestJs的验证流水线真的不错不比SpringBoot差,官方的《下一代Node.js全栈开发框架》好像真的没cover啊!感觉有收获的赶快分享给更多的朋友吧有需要的,谢谢!如果大家想交流更多关于NestJs的知识,欢迎加入群讨论!