Nestjs项目实战 异常处理与全局异常过滤器

在Nestjs项目中,如何优雅地实现全局异常处理?我在使用内置的HttpException时发现无法满足自定义错误格式的需求,尝试创建全局过滤器但遇到以下问题:1. 继承自BaseExceptionFilter的过滤器无法正确处理非HTTP异常;2.在不同模块中抛出的业务异常如何统一格式返回客户端?3.如何在过滤器中区分生产环境和开发环境的错误响应?4.对第三方库抛出的非标准异常该如何封装?希望有实战经验的朋友能分享具体实现方案和最佳实践。

3 回复

在NestJS项目中,异常处理非常重要。首先创建一个全局异常过滤器,通过实现 ExceptionFilter 接口完成。例如:

import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';

@Catch(HttpException)
export class AllExceptionsFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const request = ctx.getRequest();
    const status = exception.getStatus();

    response.status(status).json({
      statusCode: status,
      timestamp: new Date().toISOString(),
      path: request.url,
    });
  }
}

然后在主文件中注册这个过滤器:

import { AllExceptionsFilter } from './filters/all-exceptions.filter';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalFilters(new AllExceptionsFilter());
  await app.listen(3000);
}
bootstrap();

这种方式能统一处理项目中的异常,返回标准的JSON格式响应。当抛出 HttpException 或其子类时,会自动触发该过滤器,避免重复编码。


在NestJS中,异常处理和全局异常过滤器是非常重要的功能。首先,创建一个自定义异常过滤器,实现ExceptionFilter接口。例如:

@Injectable()
export class AllExceptionsFilter implements ExceptionFilter {
  catch(exception: unknown, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const request = ctx.getRequest();

    console.error(exception);

    response.status(500).json({
      statusCode: 500,
      timestamp: new Date().toISOString(),
      path: request.url,
    });
  }
}

然后,在模块中注册该过滤器为全局过滤器:

@Module({
  providers: [
    {
      provide: APP_FILTER,
      useClass: AllExceptionsFilter,
    },
  ],
})
export class AppModule {}

这样,所有未捕获的异常都会被这个过滤器捕获并返回统一的错误响应。如果需要针对特定类型的异常进行特殊处理,可以在过滤器中添加条件判断。此外,还可以通过@Catch()装饰器来指定要捕获的具体异常类型。

NestJS项目实战:异常处理与全局异常过滤器

在NestJS中,异常处理是一个重要环节,良好的异常处理可以提升应用的健壮性和可维护性。

基础异常类

NestJS内置了HttpException类,我们可以直接使用或继承它:

throw new HttpException('资源不存在', HttpStatus.NOT_FOUND);

自定义异常

可以创建自己的异常类:

export class BusinessException extends HttpException {
  constructor(message: string, code: number) {
    super({ message, code }, HttpStatus.BAD_REQUEST);
  }
}

全局异常过滤器

创建全局异常过滤器是推荐做法:

import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { Request, Response } from 'express';

@Catch()
export class GlobalExceptionFilter implements ExceptionFilter {
  catch(exception: unknown, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();

    let status = 500;
    let message = 'Internal server error';
    let errorCode = 'INTERNAL_ERROR';

    if (exception instanceof HttpException) {
      status = exception.getStatus();
      const exceptionResponse = exception.getResponse();
      if (typeof exceptionResponse === 'object') {
        message = exceptionResponse['message'] || message;
        errorCode = exceptionResponse['errorCode'] || errorCode;
      } else {
        message = exceptionResponse;
      }
    }

    response.status(status).json({
      statusCode: status,
      timestamp: new Date().toISOString(),
      path: request.url,
      message,
      errorCode
    });
  }
}

注册全局过滤器

main.ts中注册:

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalFilters(new GlobalExceptionFilter());
  await app.listen(3000);
}
bootstrap();

业务层异常处理

在服务层抛出业务异常:

async findOne(id: number) {
  const user = await this.userRepository.findOne(id);
  if (!user) {
    throw new BusinessException('用户不存在', 'USER_NOT_FOUND');
  }
  return user;
}

这样构建的异常处理系统可以提供统一的错误响应格式,便于前端处理和后端调试。

回到顶部