抛出HttpException后NestJS服务崩溃问题求助
环境信息
// package.json "@nestjs/common": "^10.0.0", "@nestjs/core": "^10.0.0", "@nestjs/platform-express": "^10.0.0", "@nestjs/typeorm": "^10.0.1", // 系统 Mac m1 // Dockerfile FROM node:21 WORKDIR /app COPY . . RUN npm install RUN npm run build EXPOSE 3000 CMD npm run start:dev
我配置了全局异常过滤器HttpExceptionFilter,但抛出HttpException后服务直接停止工作,后续所有请求都返回Error: read ECONNRESET,Docker控制台不再接收请求。
代码情况
- 全局过滤器配置(main.ts):
async function bootstrap() { const app = await NestFactory.create(AppModule); app.setGlobalPrefix('api'); app.useGlobalFilters(new HttpExceptionFilter()); await app.listen(3000); } bootstrap();
- 异常过滤器实现:
@Catch(HttpException) export class HttpExceptionFilter implements ExceptionFilter { catch(exception: HttpException, host: ArgumentsHost) { console.log('filter'); const ctx = host.switchToHttp(); const response = ctx.getResponse<Response>(); const request = ctx.getRequest<Request>(); const status = exception.getStatus(); response.status(status).json({ statusCode: status, message: exception.message, timestamp: new Date().toISOString(), path: request.url, }); } }
- 业务代码:
StudiesService中的getStudyById和deleteStudyById方法,在数据不存在时会抛出NotFoundException或HttpException;StudiesController中GET /:id返回Promise,DELETE /:id未返回Promise。
问题现象
- 正常请求(如
GET localhost:3000/api/studies/2)可收到正确响应; - 发送
DELETE localhost:3000/api/studies/100(ID不存在)触发异常时,Docker控制台打印异常栈,服务崩溃; - 后续任何请求都返回
Error: read ECONNRESET; - 特殊情况:
GET请求触发异常时,过滤器正常工作,服务不会崩溃。
问题求助
为何DELETE请求触发异常会导致服务崩溃,如何解决?
原因分析
问题核心在于DELETE /:id的控制器方法未返回Promise。NestJS中,异步控制器方法如果不返回Promise,内部抛出的异常无法被Nest正确捕获并传递给异常过滤器,最终会触发未处理的Promise拒绝,导致Node.js进程直接崩溃(Node.js默认会终止存在未处理Promise拒绝的进程)。
而GET方法返回了Promise,Nest能完整追踪异步流程,异常会被正常传递给全局过滤器处理,因此不会引发服务崩溃。
解决方法
修改StudiesController中的DELETE /:id方法,确保它返回Promise:
示例修改
假设原代码是:
@Delete(':id') deleteStudyById(@Param('id') id: string) { this.studiesService.deleteStudyById(id); }
改成:
@Delete(':id') async deleteStudyById(@Param('id') id: string) { return this.studiesService.deleteStudyById(id); }
或者手动封装Promise返回:
@Delete(':id') deleteStudyById(@Param('id') id: string) { return Promise.resolve(this.studiesService.deleteStudyById(id)); }
这样Nest就能正确捕获异步操作中的异常,交给全局过滤器处理,避免服务崩溃。
额外防护(可选)
为了避免其他未处理的Promise拒绝导致服务崩溃,可以在项目入口添加全局监听:
async function bootstrap() { // ... 现有代码 process.on('unhandledRejection', (reason, promise) => { console.error('未处理的Promise拒绝:', reason); // 可添加日志上报等逻辑,但核心还是要确保所有异步控制器方法返回Promise }); } bootstrap();
内容的提问来源于stack exchange,提问作者nayounsang
相关产品推荐
相关产品推荐

