javascript - Hur kan jag hantera TypeORM-fel i NestJS?
Jag skulle vilja skapa ett anpassat undantagsfilter som hanterar olika typer av TypeORM-fel. Jag har tittat upp TypeORM-felklasserna, och det verkar som att det inte finns något sådant i TypeORM som MongoError.
Jag ville göra något liknande 1FpGLLjZSZMx6k:s svar, och här är vad jag har gjort hittills.
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);
}
}
Om jag behöver fånga ett annat fel till exempel, EntityNotFoundError, måste jag skriva samma kod vilket är en mycket besvärlig uppgift att göra.
Det vore trevligt om jag kunde hantera fel med ett enda filter som nedan. Några idéer?
@Catch(TypeORMError)
export class EntityNotFoundExceptionFilter implements ExceptionFilter {
catch(exception: MongoError, host: ArgumentsHost) {
switch (exception.code) {
case some error code:
// handle error
}
}
}
Svar #1
För att hantera olika typer av TypeOrm-fel kan du använda switch/case på undantagskonstruktorn om den matchar något TypeOrm-fel (från node_modules\typeorm\error). Dessutom kommer (exception as any).code att ge det faktiska databasfelet som uppstod. Observera att @catch() dekoratören är tom för att kunna fånga alla feltyper.
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;
}
Obs: Från och med den nya versionen av typeorm kommer importen för EntityNotFoundError och CannotCreateEntityIdMapError att vara enligt nedan
import { QueryFailedError } from 'typeorm';
import { EntityNotFoundError } from 'typeorm/error/EntityNotFoundError';
import { CannotCreateEntityIdMapError } from 'typeorm/error/CannotCreateEntityIdMapError';
Svar #2
I dokumentationen står det:
Dekoratören
@Catch()kan ta ett enskilt parameter, eller en kommaseparerad lista. Detta låter dig ställa in filtret för flera typer av undantag samtidigt.
Så i ditt fall skulle du kunna skriva:
@Catch(QueryFailedError, EntityNotFoundError)
