NestJS错误处理规范
在NestJS项目中,应该如何规范地处理全局错误?目前使用HTTP异常过滤器时,遇到几个问题:
- 无法自动捕获非HTTP类型的底层错误(如数据库操作失败);
- 自定义业务错误码难以与HTTP状态码映射;
- 开发环境和生产环境的错误信息展示差异如何处理?是否有推荐的分层处理方案,比如业务校验层、Service层和Controller层的错误该如何区分处理?官方文档的异常过滤器案例感觉不够完整,求实际项目中的最佳实践。
在NestJS中,错误处理应遵循以下规范:
-
统一错误响应格式:所有错误返回的格式需一致,通常包括
status
、message
和error
字段。例如:{ "status": 500, "message": "Internal server error", "error": "InternalServerError" }
-
使用
[@Catch](/user/Catch)()
装饰器:通过[@Catch](/user/Catch)()
装饰器捕获全局异常,定义AppController
或独立的ExceptionFilter
类处理异常。 -
自定义异常类:创建继承自
HttpException
的自定义异常类,便于区分不同类型的错误。例如:class CustomException extends HttpException { constructor() { super('Custom Error Message', HttpStatus.BAD_REQUEST); } }
-
错误日志记录:利用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' }); } }
-
业务逻辑错误处理:对于业务逻辑错误,使用
throw new HttpException()
抛出,并在全局过滤器中统一处理。
在NestJS中,错误处理应遵循以下规范:
-
自定义异常类:创建继承自
HttpException
的自定义异常类,用于表示特定业务逻辑错误。例如:export class BadRequestException extends HttpException { constructor() { super('Bad Request', HttpStatus.BAD_REQUEST); } }
-
全局异常过滤器:通过实现
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', }); } }
-
模块级异常过滤器:针对特定模块或控制器,可创建局部异常过滤器。
-
日志记录:在异常处理时记录错误信息,便于后续排查问题。
-
错误码与国际化:为每种错误定义唯一错误码,并支持多语言处理,提升用户体验。
-
避免直接抛出内置异常:尽量使用自定义异常类,便于后续维护和扩展。
在 NestJS 中,错误处理是一个重要的环节,以下是常见的规范和最佳实践:
- HTTP异常类(内置)
throw new BadRequestException('Invalid input');
throw new NotFoundException('User not found');
// 其他内置HTTP异常:
// - UnauthorizedException
// - ForbiddenException
// - NotAcceptableException
// - RequestTimeoutException
// - ConflictException
// - InternalServerErrorException
- 自定义异常过滤器
@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 {}
- 全局异常处理
// 在main.ts中
app.useGlobalFilters(new HttpExceptionFilter());
- 最佳实践建议
- 业务逻辑错误使用自定义异常类
- 保持错误信息一致性(统一响应格式)
- 对敏感信息进行过滤
- 区分客户端错误(4xx)和服务器错误(5xx)
- 生产环境隐藏技术细节
- 日志记录 建议结合Logger服务记录错误:
private readonly logger = new Logger(MyService.name);
try {
// ...
} catch (error) {
this.logger.error(`操作失败: ${error.message}`, error.stack);
throw new InternalServerErrorException('操作失败');
}
- 验证错误处理 使用ValidationPipe时自动返回400错误:
app.useGlobalPipes(new ValidationPipe({
exceptionFactory: (errors) => new BadRequestException(errors)
}));
这些规范可以帮助你构建更健壮的NestJS应用,保持错误处理的一致性和可维护性。