NestJS бросить из ExceptionFilter - PullRequest
0 голосов
/ 01 марта 2019

Я пытаюсь использовать ExceptionFilter для сопоставления исключений с их HTTP-аналогом.

Это мой код:

@Catch(EntityNotFoundError)
export class EntityNotFoundFilter implements ExceptionFilter {
    catch(exception: EntityNotFoundError, _host: ArgumentsHost) {
        throw new NotFoundException(exception.message);
    }
}

Но, когда код фильтра выполняется, я получилa UnhandledPromiseRejectionWarning

 (node:3065) UnhandledPromiseRejectionWarning: Error: [object Object]
    at EntityNotFoundFilter.catch ([...]/errors.ts:32:15)
    at ExceptionsHandler.invokeCustomFilters ([...]/node_modules/@nestjs/core/exceptions/exceptions-handler.js:49:26)
     at ExceptionsHandler.next ([...]/node_modules/@nestjs/core/exceptions/exceptions-handler.js:13:18)
     at [...]/node_modules/@nestjs/core/router/router-proxy.js:12:35
     at <anonymous>
     at process._tickCallback (internal/process/next_tick.js:182:7)
 (node:3065) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 5)

Как я могу это исправить?

Ответы [ 3 ]

0 голосов
/ 01 марта 2019

Основываясь на решении Ким Керн, я создал этот абстрактный класс

export abstract class AbstractErrorInterceptor<T> implements NestInterceptor {
    protected interceptedType: new (...args) => T;

    intercept(
        context: ExecutionContext,
        call$: Observable<any>,
    ): Observable<any> | Promise<Observable<any>> {
        return call$.pipe(
            catchError(exception => {
                if (exception instanceof this.interceptedType) {
                    this.handleError(exception);
                }
                throw exception;
            }),
        );
    }

    abstract handleError(exception: T);
}

И некоторые реализации

export class EntityNotFoundFilter extends AbstractErrorInterceptor<EntityNotFoundError> {
    interceptedType = EntityNotFoundError;

    handleError(exception: EntityNotFoundError) {
        throw new NotFoundException(exception.message);
    }
}
0 голосов
/ 01 марта 2019

Кажется странным, что вы создаете свою собственную версию классов исключений на основе HTTP, которые уже поставляются с NestJS.По умолчанию они автоматически преобразуются в ответы HTTP с правильными кодами ошибок.Вы добавляете накладные расходы с перехватчиками и реализациями абстрактных классов, когда вместо этого вы можете просто генерировать ошибки NestJS и получать их бесплатно.Это встроенный механизм, на который вы ссылались.

throw new BadRequestException('you done goofed');

приводит к:

{"statusCode":400,"error":"Bad Request","message":"you done goofed"}

Codesandbox(адаптировано из Ким)

0 голосов
/ 01 марта 2019

ExceptionFilter всегда является последним местом, которое вызывается перед отправкой ответа, оно отвечает за построение ответа.Вы не можете повторно выбросить исключение из ExceptionFilter.

@Catch(EntityNotFoundError)
export class EntityNotFoundFilter implements ExceptionFilter {
  catch(exception: EntityNotFoundError, host: ArgumentsHost) {
    const response = host.switchToHttp().getResponse();
      response.status(404).json({ message: exception.message });
  }
}

В качестве альтернативы, вы можете создать 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;
        }
      }));
  }
}

Попробуйте это в этом коде и ящике .

...