nestjs 错误处理方法是什么(业务逻辑错误 vs. http 错误)?

新手上路,请多包涵

在使用 NestJS 创建 API 时,我想知道哪种方法是处理错误/异常的最佳方式。我发现了两种不同的方法:

  1. Have individual services and validation pipes throw new Error() , have the controller catch them and then throw the appropriate kind of HttpException ( BadRequestException , ForbiddenException 等等..)
  2. 让控制器简单地调用负责处理那部分业务逻辑的服务/验证管道方法,并抛出适当的 HttpException

两种方法各有利弊:

  1. 这似乎是正确的方法,但是,服务可以返回 Error 出于不同的原因,我如何从控制器知道哪种类型的 HttpException 要返回?
  2. 非常灵活,但是服务中有 Http 相关内容似乎是错误的。

我想知道,哪一种(如果有的话)是“nest js”的实现方式?

你是怎么处理这件事的?

原文由 Aaron Ullal 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 680
2 个回答

假设您的业务逻辑抛出 EntityNotFoundError 并且您希望将其映射到 NotFoundException

为此,您可以创建一个 Interceptor 来转换您的错误:

 @Injectable()
export class NotFoundInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    // next.handle() is an Observable of the controller's result value
    return next.handle()
      .pipe(catchError(error => {
        if (error instanceof EntityNotFoundError) {
          throw new NotFoundException(error.message);
        } else {
          throw error;
        }
      }));
  }
}

然后,您可以通过将 @UseInterceptors(NotFoundInterceptor) 添加到控制器的类或方法中来使用它;甚至作为所有路线的全球拦截器。当然,你也可以在一个拦截器中映射多个错误。

在此 codeandbox 中尝试一下。

原文由 Kim Kern 发布,翻译遵循 CC BY-SA 4.0 许可协议

Nest Js 提供了一个异常过滤器,用于处理应用层未处理的错误,因此我将其修改为返回 500,即非 Http 异常的内部服务器错误。然后将异常记录到服务器,然后你就可以知道出了什么问题并修复它。

 import 'dotenv/config';
import { ArgumentsHost, Catch, ExceptionFilter, HttpException, HttpStatus, Logger } from '@nestjs/common';

@Catch()
export class HttpErrorFilter implements ExceptionFilter {
  private readonly logger : Logger
  constructor(){
    this.logger = new Logger
  }
  catch(exception: Error, host: ArgumentsHost): any {
    const ctx = host.switchToHttp();
    const request = ctx.getRequest();
    const response = ctx.getResponse();

    const statusCode = exception instanceof HttpException ? exception.getStatus() : HttpStatus.INTERNAL_SERVER_ERROR
    const message = exception instanceof HttpException ?  exception.message || exception.message?.error: 'Internal server error'

    const devErrorResponse: any = {
      statusCode,
      timestamp: new Date().toISOString(),
      path: request.url,
      method: request.method,
      errorName: exception?.name,
      message: exception?.message
    };

    const prodErrorResponse: any = {
      statusCode,
      message
    };
    this.logger.log( `request method: ${request.method} request url${request.url}`, JSON.stringify(devErrorResponse));
    response.status(statusCode).json( process.env.NODE_ENV === 'development'? devErrorResponse: prodErrorResponse);
  }
}

原文由 Ukpa Uchechi 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题