我正在重构的 NestJS 应用程序上运行一些手动测试,刚刚从 Nest 的全局异常过滤器中发现了奇怪的行为。 创建该项目的开发人员将其用作异常过滤器:
import {
ExceptionFilter,
Catch,
ArgumentsHost,
HttpException,
HttpStatus,
} from '@nestjs/common';
import { HttpAdapterHost } from '@nestjs/core';
import { LoggerService } from '../../config/logger.service';
@Catch()
export class GlobalExceptionsFilter implements ExceptionFilter {
constructor(
private readonly httpAdapterHost: HttpAdapterHost,
private readonly logger: LoggerService,
) {}
catch(exception: Error, host: ArgumentsHost): void {
const { httpAdapter } = this.httpAdapterHost;
const ctx = host.switchToHttp();
const httpStatus =
exception instanceof HttpException
? exception.getStatus()
: HttpStatus.INTERNAL_SERVER_ERROR;
const responseBody = {
statusCode: httpStatus,
path: httpAdapter.getRequestUrl(ctx.getRequest()),
cause: `${exception.name}: ${exception.message}`,
timestamp: new Date().toISOString(),
};
this.logger.error(responseBody?.cause);
httpAdapter.reply(ctx.getResponse(), responseBody, httpStatus);
}
}
这与 Nest 文档中的捕获一切过滤器示例几乎完全相同,因此它确实非常通用。
在这个项目的某个部分,有一个控制器有这样的东西:
@OnEvent(Events.POTATO_EVENT)
async potatoMethod(payload) {
return await this.service.potatoMethod(payload);
目前,服务的
potatoMethod
上没有有效负载验证,因此控制器使用 EventEmitter2
从另一个服务接收有效负载并将其转发到其服务,然后该服务尝试通过调用 ORM 方法在数据库中获取记录。
如果 payload.potatoNumber
发送正确,不会发生任何错误,但如果我将 payload.potatoNumber
发送为未定义,ORM 将抛出一个错误,该错误不会被该全局过滤器捕获。
如果我不使用 @OnEvent()
,而是直接在控制器上使用 @Get()
将其变成端点,则不会发生同样的事情。
目前,
main
看起来像这样:
(async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
})();
我可能完全错了,但这只有在应用程序未在其
NestFactory.createMicroservice()
文件上使用 main.ts
时才会发生,对吗?如果是的话,微服务在 Nest 中到底是如何工作的?
我也对 nestjs 事件发射器 1.4.1 中的这种行为感到有点措手不及,但同时它的发生也是有道理的,除非你自己处理这些异常。
但他们最终在 https://github.com/nestjs/event-emitter/pull/908 中添加了这种类型的处理,因此您只需要更新到事件发射器 2.0.1 或更高版本(2.0.4 at这个答案的时间)。