1、统一异常处理
1.1、使用nest内置HttpException
nestjs内置了HttpException以及HttpStatus状态码,使用方法如下:
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(params): string {
if(!params.id){
throw new HttpException('id is required', HttpStatus.BAD_REQUEST)
}
return 'Hello World!';
}
}
运行程序并在浏览器中输入http://localhost:8000,系统显示如下:
修改正确的参数则显示如下:
nest系统中还定义了一些其他常见的 HTTP 异常,如:
BadRequestExceptionUnauthorizedExceptionNotFoundExceptionForbiddenExceptionNotAcceptableExceptionRequestTimeoutExceptionConflictExceptionGoneExceptionHttpVersionNotSupportedExceptionPayloadTooLargeExceptionUnsupportedMediaTypeExceptionUnprocessableEntityExceptionInternalServerErrorExceptionNotImplementedExceptionImATeapotExceptionMethodNotAllowedExceptionBadGatewayExceptionServiceUnavailableExceptionGatewayTimeoutException- `PreconditionFailedException
1.2、自定义异常
管理框架的一些通用设置项一般放在common目录下,所以在src下新建common/exceptions/forbidden.exception.ts 文件,内容如下:
import { HttpException, HttpStatus } from "@nestjs/common";
//自定义异常继承HttpException
export class ForbiddenException extends HttpException {
constructor() {
//构造函数中调用父方法,并传入错误消息和状态码
super('自定义错误',HttpStatus.FORBIDDEN);
}
}
修改app.service代码,测试自定义异常:
1.3、统一异常返回内容
一般使用过滤器在返回异常前对异常信息进行一些处理,返回格式一致的信息,方便前端调用。
在common/filters目录下新建http-exception.filter.ts文件,代码如下:
import { ExceptionFilter, Catch, ArgumentsHost, HttpException, Injectable } from '@nestjs/common';
import { Request, Response } from 'express';
//注解捕获http异常
@Catch(HttpException)
//继承自ExceptionFilter过滤器
export class HttpExceptionFilter implements ExceptionFilter {
//实现catch方法
catch(exception: HttpException, host: ArgumentsHost) {
//获取Http上下文
const ctx = host.switchToHttp();
//获取响应对象
const response = ctx.getResponse<Response>();
//const request = ctx.getRequest<Request>();
//获取状态码
const status = exception.getStatus();
//返回错误信息
response
.status(status)
.json({
code: status,
message: exception.message,
});
}
}
HttpExceptionFilter 类 :使用 @Catch(HttpException) 装饰器捕获所有的 HttpException 异常。在 catch 方法中,获取请求和响应上下文,然后根据异常的状态码和消息,返回统一格式的 JSON 响应。
在main.ts中增加全局过滤器:
//注册全局异常过滤器,返回统一的格式
app.useGlobalFilters(new HttpExceptionFilter());
通过 app.useGlobalFilters(new HttpExceptionFilter()) 全局注册异常过滤器,这样所有的控制器都会使用这个过滤器来处理异常。
测试:
2、统一的请求响应成功拦截器
我们还需要一个返回格式的拦截器对请求成功(状态码为 2xx)的数据进行一个格式化,比如返回这样的格式:{code:200,data:T,message:string}
2.1、生成拦截器
nest g interceptor common/interceptors/transform --no-spec
代码:
import {
Injectable,
NestInterceptor,
ExecutionContext,
CallHandler,
} from "@nestjs/common";
import { Observable } from "rxjs";
import { map } from "rxjs/operators";
export interface Response<T> {
data: T;
}
@Injectable()
export class TransformInterceptor<T>
implements NestInterceptor<T, Response<T>>
{
intercept(
context: ExecutionContext,
next: CallHandler
): Observable<Response<T>> {
return next
.handle()
.pipe(map((data) => ({ code: 200, data, describe: "请求成功" })));
}
}
2.2、同样的在 main.ts 中进行全局注册
//注册全局拦截器,返回统一的格式 配置到module中了
app.useGlobalInterceptors(new TransformInterceptor());