【问题标题】:How can I handle TypeORM error in NestJS?如何处理 NestJS 中的 TypeORM 错误?
【发布时间】:2020-03-18 11:26:13
【问题描述】:

我想创建一个自定义异常过滤器来处理不同类型的 TypeORM 错误。我查了TypeORM error classes,好像TypeORM中没有MongoError这样的东西。

我想做类似于1FpGLLjZSZMx6k's answer 的东西,这就是我目前所做的。

import { QueryFailedError } from 'typeorm';

@Catch(QueryFailedError)
export class QueryFailedExceptionFilter implements ExceptionFilter {
  catch(exception: QueryFailedError, host: ArgumentsHost) {
    const context = host.switchToHttp();
    const response = context.getResponse<Response>();
    const request = context.getRequest<Request>();
    const { url } = request;
    const { name } = exception;
    const errorResponse = {
      path: url,
      timestamp: new Date().toISOString(),
      message: name,
    };

    response.status(HttpStatus.BAD_REQUEST).json(errorResponse);
  }
}

如果我需要捕获另一个错误,例如EntityNotFoundError,我必须编写相同的代码,这是一项非常繁琐的任务。

如果我可以通过如下所示的单个过滤器处理错误,那就太好了。有什么想法吗?

@Catch(TypeORMError)
export class EntityNotFoundExceptionFilter implements ExceptionFilter {
  catch(exception: MongoError, host: ArgumentsHost) {
    switch (exception.code) {
      case some error code:
        // handle error
    }
  }
}

【问题讨论】:

    标签: javascript node.js typescript nestjs typeorm


    【解决方案1】:

    documentation 中,它说:

    @Catch() 装饰器可以采用单个参数,或 逗号分隔列表。这使您可以设置多个过滤器 类型的异常。

    所以在你的情况下你可以写:

    @Catch(QueryFailedError, EntityNotFoundError)
    

    【讨论】:

    • 感谢您的回复。那么我应该如何处理不同的异常呢? catch() 方法中的第一个参数是什么?
    • @JeffMinsungKim 因为它们都扩展了Error,所以类型可以是Error,也可以是QueryFailedError | EntityNotFoundError 类型的显式列表。如果您有特定于某些错误的代码,您可以使用instanceof 保护此逻辑。
    【解决方案2】:

    要处理不同类型的 TypeOrm 错误,如果异常构造函数匹配任何 TypeOrm 错误(来自 node_modules\typeorm\error),您可以切换/ case。此外, (exception as any).code 将提供发生的实际数据库错误。注意 @catch() 装饰器是空的,以便捕获所有错误类型。

    import { ArgumentsHost, Catch, ExceptionFilter, HttpException, HttpStatus, Logger } from '@nestjs/common';
    import { Request, Response } from 'express';
    import { QueryFailedError, EntityNotFoundError, CannotCreateEntityIdMapError } from 'typeorm';
    import { GlobalResponseError } from './global.response.error';
    
    @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 message = (exception as any).message.message;
            let code = 'HttpException';
    
            Logger.error(message, (exception as any).stack, `${request.method} ${request.url}`);
    
            let status = HttpStatus.INTERNAL_SERVER_ERROR;
            
            switch (exception.constructor) {
                case HttpException:
                    status = (exception as HttpException).getStatus();
                    break;
                case QueryFailedError:  // this is a TypeOrm error
                    status = HttpStatus.UNPROCESSABLE_ENTITY
                    message = (exception as QueryFailedError).message;
                    code = (exception as any).code;
                    break;
                case EntityNotFoundError:  // this is another TypeOrm error
                    status = HttpStatus.UNPROCESSABLE_ENTITY
                    message = (exception as EntityNotFoundError).message;
                    code = (exception as any).code;
                    break;
                case CannotCreateEntityIdMapError: // and another
                    status = HttpStatus.UNPROCESSABLE_ENTITY
                    message = (exception as CannotCreateEntityIdMapError).message;
                    code = (exception as any).code;
                    break;
                default:
                    status = HttpStatus.INTERNAL_SERVER_ERROR
            }
    
            response.status(status).json(GlobalResponseError(status, message, code, request));
        }
    }
    
    
    import { Request } from 'express';
    import { IResponseError } from './response.error.interface';
    
    export const GlobalResponseError: (statusCode: number, message: string, code: string, request: Request) => IResponseError = (
        statusCode: number,
        message: string,
        code: string,
        request: Request
    ): IResponseError => {
        return {
            statusCode: statusCode,
            message,
            code,
            timestamp: new Date().toISOString(),
            path: request.url,
            method: request.method
        };
    };
    
    
    export interface IResponseError {
        statusCode: number;
        message: string;
        code: string;
        timestamp: string;
        path: string;
        method: string;
    }
    

    【讨论】:

    • 感谢您提供全面的示例。我用它作为我项目中 NestJS 错误处理的模板。
    【解决方案3】:

    import { ArgumentsHost, Catch, ExceptionFilter } from '@nestjs/common';
    import { TypeORMError } from 'typeorm';
    import { ErrorMessage } from '../error.interface';
    
    @Catch(TypeORMError)
    export class TypeOrmFilter implements ExceptionFilter {
        catch(exception: TypeORMError, host: ArgumentsHost) {
            const response = host.switchToHttp().getResponse();
            let message: string = (exception as TypeORMError).message;
            let code: number = (exception as any).code;
            const customResponse: ErrorMessage = {
                status: 500,
                message: 'Something Went Wrong',
                type: 'Internal Server Error',
                errors: [{ code: code, message: message }],
                errorCode: 300,
                timestamp: new Date().toISOString(),
            };
    
            response.status(customResponse.status).json(customResponse);
        }
    }

    【讨论】:

    • 请提供有关您的解决方案的更多详细信息,而不仅仅是代码。
    • 请分享,如何以及在哪里使用这个实现。像这样的答案没有任何好处
    猜你喜欢
    • 2018-07-28
    • 1970-01-01
    • 2019-11-25
    • 2021-12-10
    • 2020-02-23
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 2021-04-23
    相关资源
    最近更新 更多