NestJS错误处理规范

在NestJS项目中,应该如何规范地处理全局错误?目前使用HTTP异常过滤器时,遇到几个问题:

  1. 无法自动捕获非HTTP类型的底层错误(如数据库操作失败);
  2. 自定义业务错误码难以与HTTP状态码映射;
  3. 开发环境和生产环境的错误信息展示差异如何处理?是否有推荐的分层处理方案,比如业务校验层、Service层和Controller层的错误该如何区分处理?官方文档的异常过滤器案例感觉不够完整,求实际项目中的最佳实践。
3 回复

在NestJS中,错误处理应遵循以下规范:

  1. 统一错误响应格式:所有错误返回的格式需一致,通常包括statusmessageerror字段。例如:

    {
      "status": 500,
      "message": "Internal server error",
      "error": "InternalServerError"
    }
    
  2. 使用[@Catch](/user/Catch)()装饰器:通过[@Catch](/user/Catch)()装饰器捕获全局异常,定义AppController或独立的ExceptionFilter类处理异常。

  3. 自定义异常类:创建继承自HttpException的自定义异常类,便于区分不同类型的错误。例如:

    class CustomException extends HttpException {
        constructor() {
            super('Custom Error Message', HttpStatus.BAD_REQUEST);
        }
    }
    
  4. 错误日志记录:利用NestJS的日志系统记录错误信息,方便排查问题。例如:

    [@Catch](/user/Catch)()
    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({
                status: 500,
                message: 'Internal Server Error',
                error: exception.name || 'Error'
            });
        }
    }
    
  5. 业务逻辑错误处理:对于业务逻辑错误,使用throw new HttpException()抛出,并在全局过滤器中统一处理。


在NestJS中,错误处理应遵循以下规范:

  1. 自定义异常类:创建继承自HttpException的自定义异常类,用于表示特定业务逻辑错误。例如:

    export class BadRequestException extends HttpException {
        constructor() {
            super('Bad Request', HttpStatus.BAD_REQUEST);
        }
    }
    
  2. 全局异常过滤器:通过实现ExceptionsHandler接口或使用[@Catch](/user/Catch)装饰器创建全局异常过滤器,统一处理异常。例如:

    [@Catch](/user/Catch)()
    export class AllExceptionsFilter implements ExceptionsHandler {
        handle(exception: any, host: ArgumentsHost) {
            const ctx = host.switchToHttp();
            const response = ctx.getResponse();
            const request = ctx.getRequest();
    
            const status = exception instanceof HttpException
                ? exception.getStatus()
                : HttpStatus.INTERNAL_SERVER_ERROR;
    
            response.status(status).json({
                statusCode: status,
                timestamp: new Date().toISOString(),
                path: request.url,
                message: exception.message || 'Internal Server Error',
            });
        }
    }
    
  3. 模块级异常过滤器:针对特定模块或控制器,可创建局部异常过滤器。

  4. 日志记录:在异常处理时记录错误信息,便于后续排查问题。

  5. 错误码与国际化:为每种错误定义唯一错误码,并支持多语言处理,提升用户体验。

  6. 避免直接抛出内置异常:尽量使用自定义异常类,便于后续维护和扩展。

在 NestJS 中,错误处理是一个重要的环节,以下是常见的规范和最佳实践:

  1. HTTP异常类(内置)
throw new BadRequestException('Invalid input');
throw new NotFoundException('User not found');
// 其他内置HTTP异常:
// - UnauthorizedException
// - ForbiddenException
// - NotAcceptableException
// - RequestTimeoutException 
// - ConflictException
// - InternalServerErrorException
  1. 自定义异常过滤器
@Catch(MyCustomError)
export class MyExceptionFilter implements ExceptionFilter {
  catch(exception: MyCustomError, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    
    response.status(500).json({
      statusCode: 500,
      message: exception.message,
      timestamp: new Date().toISOString()
    });
  }
}

// 使用方式:
@UseFilters(new MyExceptionFilter())
@Controller()
export class AppController {}
  1. 全局异常处理
// 在main.ts中
app.useGlobalFilters(new HttpExceptionFilter());
  1. 最佳实践建议
  • 业务逻辑错误使用自定义异常类
  • 保持错误信息一致性(统一响应格式)
  • 对敏感信息进行过滤
  • 区分客户端错误(4xx)和服务器错误(5xx)
  • 生产环境隐藏技术细节
  1. 日志记录 建议结合Logger服务记录错误:
private readonly logger = new Logger(MyService.name);

try {
  // ...
} catch (error) {
  this.logger.error(`操作失败: ${error.message}`, error.stack);
  throw new InternalServerErrorException('操作失败');
}
  1. 验证错误处理 使用ValidationPipe时自动返回400错误:
app.useGlobalPipes(new ValidationPipe({
  exceptionFactory: (errors) => new BadRequestException(errors)
}));

这些规范可以帮助你构建更健壮的NestJS应用,保持错误处理的一致性和可维护性。

回到顶部