You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

未处理异常致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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 02:25:00