{
"code": 0,
"message": "OK",
"data": []
}
{
"code": -1,
"message": "error reason",
"data": null
}
这里我们借助拦截器来实现
使用命令创建一个拦截器
nest g interceptor transform
import {
CallHandler,
ExecutionContext,
Injectable,
NestInterceptor,
} from '@nestjs/common';
import { Observable, map } from 'rxjs';
/**
* 拦截器 返回统一响应格式
*/
@Injectable()
export class TransformInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
return next.handle().pipe(
map((data) => {
return {
data,
code: 0,
msg: '请求成功',
};
}),
);
}
}
handle() 返回一个 Observable。此流包含从路由处理程序返回的值, 因此我们可以使用 map() 运算符轻松地对其进行改变。
全局注册我们刚创建好的拦截器
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { TransformInterceptor } from './core/interceptor/transform.interceptor';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// 全局注册拦截器
app.useGlobalInterceptors(new TransformInterceptor());
await app.listen(3000);
}
bootstrap();
使用命令创建一个异常过滤器
nest g filter http-exception
创建好后,实现HttpExceptionFilter,捕获作为HttpException类实例的异常,并为它们设置自定义响应逻辑。
import {
ArgumentsHost,
Catch,
ExceptionFilter,
HttpException,
} from '@nestjs/common';
/**
* 异常过滤器 异常返回统一响应
* 捕获作为HttpException类实例的异常,并为它们设置自定义响应逻辑
*/
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
// 获取请求上下文
const ctx = host.switchToHttp();
// 获取请求上下文中的 response对象
const response = ctx.getResponse();
// 获取异常状态码
const status = exception.getStatus();
// 异常消息
const message = exception.message ? exception.message : 'Service Error';
// Response.json()方法,使用 Response对象直接控制发送的响应。
response.status(status).json({
code: -1,
message: message,
data: null,
});
}
}
全局注册异常过滤器
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { HttpExceptionFilter } from './core/filter/http-exception.filter';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// 全局注册异常过滤器
app.useGlobalFilters(new HttpExceptionFilter());
await app.listen(3000);
}
bootstrap();
抛出异常,在service中使用并抛出异常
import { HttpException, HttpStatus } from '@nestjs/common';
async findAll() {
throw new HttpException('获取数据失败', HttpStatus.BAD_REQUEST);
}
HttpException 构造函数有两个必要的参数来决定响应:
response 参数定义 JSON 响应体。它可以是 string 或 object
status参数定义HTTP状态代码。
仅覆盖 JSON 响应主体的消息部分,请在 response参数中提供一个 string。
要覆盖整个 JSON 响应主体,请在response 参数中传递一个object。 Nest将序列化对象,并将其作为JSON 响应返回。
第二个构造函数参数-status-是有效的 HTTP 状态代码。 最佳实践是使用从@nestjs/common导入的 HttpStatus枚举。
以下是几个常见的状态枚举值
HttpStatus.BAD_REQUEST
HttpStatus.FORBIDDEN
HttpStatus.INTERNAL_SERVER_ERROR
为了方便,Nest 提供了一系列继承自核心异常 HttpException 的可用异常
BadRequestException
UnauthorizedException
NotFoundException
ForbiddenException
NotAcceptableException
RequestTimeoutException
ConflictException
GoneException
PayloadTooLargeException
UnsupportedMediaTypeException
UnprocessableException
InternalServerErrorException
NotImplementedException
BadGatewayException
ServiceUnavailableException
GatewayTimeoutException
HttpStatus和HttpException异常都来自@nestjs/common包中
修改之前的,我们直接使用BadRequestException来抛出异常
// 之前方式
async findAll() {
throw new HttpException('获取数据失败', HttpStatus.BAD_REQUEST);
}
// 现在方式
async findAll() {
throw new BadRequestException('获取数据失败');
}
Nest自带九个开箱即用的管道,他们从 @nestjs/common 包中导出
ValidationPipe
ParseIntPipe
ParseFloatPipe
ParseBoolPipe
ParseArrayPipe
ParseUUIDPipe
ParseEnumPipe
DefaultValuePipe
ParseFilePipe
其中ValidationPipe 配合class-validator就可以完美的实现我们想要的效果(对参数类型进行验证,验证失败抛出异常)。
管道验证操作通常用在dto这种传输层的文件中,用作验证操作。首先我们安装两个需要的依赖包:class-transformer和class-validator
yarn add class-validator class-transformer
更多关于class-validator的用法,可以查看阅读官方文档https://github.com/typestack/class-validator#validation-messages
import { IsString, IsNotEmpty } from 'class-validator';
/**
* 请求参数验证
*/
export class CreateLinkDto {
@IsString()
@IsNotEmpty({ message: '请输入链接名称' })
readonly name: string;
@IsString()
@IsNotEmpty({ message: '请输入链接地址' })
readonly url: string;
}
import {
ArgumentsHost,
Catch,
ExceptionFilter,
HttpException,
} from '@nestjs/common';
/**
* 异常过滤器 异常返回统一响应
* 捕获作为HttpException类实例的异常,并为它们设置自定义响应逻辑
*/
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
// 获取请求上下文
const ctx = host.switchToHttp();
// 获取请求上下文中的 response对象
const response = ctx.getResponse();
// 获取异常状态码
const status = exception.getStatus();
let validMessage = '';
// exceptionResponse返回结果格式: { message: [ '请输入链接名称' ], error: 'Bad Request', statusCode: 400 }
// exceptionResponse {
// message: [ 'name must be a string', '请输入链接名称' ],
// error: 'Bad Request',
// statusCode: 400
// }
const exceptionResponse: any = exception.getResponse();
// 考虑异常返回object类型的请求
if (typeof exceptionResponse === 'object') {
validMessage =
typeof exceptionResponse.message === 'string'
? exceptionResponse.message
: exceptionResponse.message[0];
}
// 异常消息
const message = exception.message ? exception.message : 'Service Error';
// Response.json()方法,使用 Response对象直接控制发送的响应。
response.status(status).json({
code: -1,
message: validMessage || message,
data: null,
});
}
}
import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from '@nestjs/common';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// 全局注册验证管道
app.useGlobalPipes(new ValidationPipe());
await app.listen(3000);
}
bootstrap();
{
"code": -1,
"message": "请输入链接名称",
"data": null
}
{
"code": -1,
"message": "name must be a string",
"data": null
}
代码已经上传到github中,欢迎大家star,持续更新,如有任何问题可以联系我v:sky201208(注明来意)
https://github.com/fozero/cloud-collect-nestjs
大家好,我是阿健Kerry,一个有趣且乐于分享的人,前小鹏汽车、货拉拉高级前端工程师,长期专注前端开发,如果你对前端&Node.js 学习进阶感兴趣的话(后续有计划也可以),可以关注我,加我微信【sky201208】,拉你进交流群一起交流、学习共同进步,群内氛围特别好,定期会组织技术分享~