未处理异常致NestJS服务崩溃,如何保障服务不中断且功能正常?
解决方案
1. 从根源杜绝漏写await的问题
用ESLint强制检查未处理的Promise,安装eslint-plugin-promise插件后,在ESLint配置文件中启用规则:
{ "plugins": ["promise"], "rules": { "promise/no-floating-promises": "error" } }
这个规则会在开发阶段直接报错任何未被await、未返回、未附加.then/.catch的Promise调用,从源头避免这类错误上线。
2. 优化全局未处理拒绝的处理逻辑
你之前的代码仅打印错误,没有清理异步上下文(如未完成的事务),导致事务资源泄漏。修改为以下逻辑:
import { QueryFailedError, getConnectionManager } from 'typeorm'; process.on('unhandledRejection', async (reason: unknown) => { console.error('未处理的Promise拒绝:', reason); // 针对TypeORM的查询失败错误,主动回滚未完成的事务 if (reason instanceof QueryFailedError) { const connection = getConnectionManager().get(reason.connectionName); if (connection.isTransactionActive) { try { await connection.rollbackTransaction(); console.log('挂起事务已回滚'); } catch (rollbackErr) { console.error('事务回滚失败:', rollbackErr); } } } // 不退出进程,确保服务继续运行 });
这样既捕获了异常,又清理了事务资源,不会影响后续功能。
3. 服务层统一规范异步操作
在NestJS的Service/Controller方法中,严格遵循两种模式:
- 所有异步操作必须加
await,确保错误能被当前上下文的异常过滤器捕获 - 若不需要立即处理结果,必须返回Promise,让上层调用链负责处理(如Controller的async方法会自动等待Promise完成)
错误示例:
async createUser(dto: UserDto) { // 漏写await,Promise脱离调用链,错误无法被捕获 this.userRepository.save(dto); }
正确示例:
// 方式1:直接await处理 async createUser(dto: UserDto) { await this.userRepository.save(dto); } // 方式2:返回Promise给上层处理 createUser(dto: UserDto) { return this.userRepository.save(dto); }
4. TypeORM事务最佳实践
尽量使用TypeORM内置的transaction方法自动管理事务,它会在异步链抛出错误时自动回滚:
async batchCreate() { await this.connection.transaction(async (manager) => { await manager.save(User, { name: 'Alice' }); await manager.save(Order, { userId: 1, amount: 100 }); }); }
注意:如果在transaction回调内漏写await,错误仍会逃逸到全局,所以还是要靠ESLint规则提前拦截。
内容的提问来源于stack exchange,提问作者WillSmith
相关产品推荐
相关产品推荐

