nestjs学习 - 异常过滤器(Exception Filter)

0 阅读3分钟

一、它是什么

官网描述:

Nest框架内置了一个异常处理层,负责处理应用程序中的所有未处理异常。当一个异常没有被应用程序代码处理时,它会被这个异常处理层捕获,然后自动发送一个适当的用户友好响应。

理解之后的描述:

统一处理应用程序中抛出的异常;

简单来说,它的作用类似于其他框架中的 “全局错误处理器” 或 AOP(面向切面编程)中的“异常通知”。当你的代码(Controller、Service、Guard、Interceptor 等)中抛出错误时,异常过滤器会捕获这些错误,然后自定义返回哪些错误信息,而不是让框架直接返回默认的原始错误堆栈信息。

需要注意的地方:

nest是内置了全局异常过滤器的;你不用做任何处理内部自动会帮你过滤异常返回给客户端;

但是通常我们是 自定义异常过滤器 来处理这些异常,正是本片文章所要介绍的内容;

二、使用方法

方法添加过滤器

@Post()
@UseFilters(new HttpExceptionFilter())
async create(@Body() createCatDto: CreateCatDto) {
  throw new ForbiddenException();
}

提示@UseFilters() 装饰器是从 @nestjs/common 包中导入的。

全局过滤器

这是一个过滤所有异常的 demo;

首先写一个简单的 过滤器

import { ExceptionFilter, Catch, ArgumentsHost, HttpException, HttpStatus } from '@nestjs/common';
import { FastifyReply, FastifyRequest } from 'fastify';
​
@Catch()
export class AnyExceptionFilter implements ExceptionFilter {
  catch(exception: unknown, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<FastifyReply>();
    const request = ctx.getRequest<FastifyRequest>();
    const status = exception instanceof HttpException ? exception.getStatus() : HttpStatus.INTERNAL_SERVER_ERROR;
    response.status(status).send({
      statusCode: status,
      timestamp: new Date().toISOString(),
      path: request.url,
      message: exception instanceof HttpException ? exception.message : 'Internal server error',
    });
  }
}

然后全局注册这个过滤器,在main.ts中

import { AnyExceptionFilter } from './common/filters/any-exception.filter';
​
async function bootstrap(): Promise<void> {
  // ...
  // 全局异常过滤器
  app.useGlobalFilters(new AnyExceptionFilter());
  // ...
}

以上就实现了一个全局异常过滤器;

例如,当我们访问一个不存在的路由时就会触发这个过滤器;

三、使用场景

在实际开发中,你通常会在以下场景中使用异常过滤器:

1. 全局统一错误处理(最常见)

你希望整个应用的所有接口在出错时,都返回相同的 JSON 格式,而不是有时返回 HTML 错误页,有时返回纯文本,有时返回不同的 JSON 结构。

  • 做法:创建一个实现 ExceptionFilter 接口的类,并使用 @UseFilters() 装饰器将其注册为全局过滤器(在 main.ts 中)。

2. 特定业务异常的精细化处理

你的应用中定义了自定义异常类(例如 InvalidApiKeyExceptionInsufficientFundsException),你需要针对这些特定异常返回特定的错误码或提示信息,而与其他普通错误区分开。

  • 做法:在过滤器中判断 exception 的类型,如果是特定类型则执行特殊逻辑。

3. 第三方库或遗留代码的错误拦截

当你调用的第三方库或直接操作的底层代码抛出了非 NestJS 标准的错误(例如原生 Node.js 错误或未被包装的 Promise rejection),你需要捕获它们并转化为 HTTP 响应,防止应用崩溃或挂起。

4. 不同环境下的差异化响应

  • 开发环境:返回详细的错误堆栈和调试信息,方便开发人员定位问题。
  • 生产环境:只返回通用的错误消息(如 "Internal Server Error"),隐藏所有技术细节以保障安全。
  • 做法:在过滤器中注入 ConfigServiceHttpAdapterHost 来判断当前环境。

5. 微服务架构中的异常转换

在微服务(TCP, Redis, MQTT 等传输层)中,异常的处理方式与 HTTP 不同。你需要编写特定的过滤器来确保微服务间的异常消息能被正确序列化和传递。