網站搜尋

javascript - 我如何在 NestJS 中處理 TypeORM 錯誤?


我想建立一個自訂的例外過濾器來處理不同種類的 TypeORM 錯誤。我查過 TypeORM 的錯誤類別,似乎在 TypeORM 中沒有像 MongoError 這樣的東西。

我想做一些類似 1FpGLLjZSZMx6k 回答的東西,這是我到目前為止所做的。

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
    }
  }
}

答案#1

要處理不同種類的 TypeOrm 錯誤,你可以使用 switch/case 來判斷例外的建構函式是否符合任何 TypeOrm 錯誤(來自 node_modules\typeorm\error)。此外,(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;
}

注意:從新版本的 typeorm 開始,EntityNotFoundError 和 CannotCreateEntityIdMapError 的匯入方式如下

import { QueryFailedError } from 'typeorm';
import { EntityNotFoundError } from 'typeorm/error/EntityNotFoundError';
import { CannotCreateEntityIdMapError } from 'typeorm/error/CannotCreateEntityIdMapError';

答案#2

在文件中,它寫道:

@Catch() 裝飾器可以接受一個參數,或逗號分隔的多個參數。這讓你可以同時為多種類型的例外設置過濾器。

所以在你的情況下你可以寫:

@Catch(QueryFailedError, EntityNotFoundError)