TSyringe注入TypeORM Repository到Provider时数据库连接未就绪问题求助
问题根因
你遇到的报错本质是TypeORM的数据库连接是异步初始化流程,而你之前的TSyringe注册、resolve逻辑是同步执行的:
- Repository构造函数中调用的
getRepository依赖已经初始化完成的TypeORM连接 - 你在导入注册文件时就同步执行了Provider的resolve逻辑,此时TypeORM还没完成连接建立,就会报实体仓库不存在的错误
- setTimeout方案只是刚好等够了连接建立的时间,但稳定性差,不同环境下连接速度波动很容易再次触发报错
方案1:绑定启动流程,等TypeORM连接就绪后再执行依赖注册
这是最稳妥的方案,把整个应用的启动逻辑改成异步串行,确保依赖按顺序初始化:
实现步骤:
- 把入口启动逻辑改成异步函数,第一步先初始化TypeORM连接
- 连接成功后再依次导入、执行Repository和Provider的注册逻辑
代码示例:
// 应用入口文件 app.ts import { createConnection } from 'typeorm'; async function bootstrap() { // 1. 优先完成数据库连接初始化 await createConnection({ // 你的TypeORM配置,也可以读ormconfig.json }); // 2. 连接成功后再注册Repository import('./shared/container/repositories'); // 3. 最后注册Provider,此时resolve依赖时Repository对应的ORM连接已经就绪 import('./shared/container/providers'); // 后续启动你的Express/Koa服务等逻辑 } bootstrap().catch(err => { console.error('应用启动失败:', err); process.exit(1); });
对应的providers/index.ts就不需要包setTimeout了,直接写原来的注册、resolve逻辑即可,因为导入的时候已经确保连接就绪。
方案2:惰性初始化Repository的ORM实例,不用调整启动顺序
如果不想改启动流程,可以修改Repository的实现,把getRepository的调用从构造函数移到实际调用时,避免实例化时就要求连接就绪:
代码示例:
export default class SafeUsdRepository implements ISafeUsdRepository { // 改成getter,只有实际调用仓库方法时才会获取ORM仓库实例,此时连接大概率已就绪 private get ormRepository(): Repository<SafeUsd> { return getRepository(SafeUsd); } // 原有其他方法完全不用改 async create(data: ICreateSafeUsdDTO): Promise<SafeUsd> { const safeUsd = this.ormRepository.create(data); await this.ormRepository.save(safeUsd); return classToClass(safeUsd); } // ... 其余方法保持不变 }
如果所有Repository都继承了公共基类,只需要改基类一次即可覆盖所有仓库,改造成本极低。
方案3:用TSyringe工厂函数实现依赖的异步初始化
也可以通过TSyringe的工厂注册能力,让依赖的实例化等待连接就绪:
代码示例:
// repositories/index.ts import { container } from 'tsyringe'; import { getConnection } from 'typeorm'; container.register<ISafeUsdRepository>('SafeUsdRepository', { useFactory: async () => { // 等待连接就绪 await getConnection(); // 初始化仓库实例 return new SafeUsdRepository(); }, });
注册Provider的时候也可以用同样的逻辑,等待依赖的Repository实例就绪后再实例化Provider。
内容的提问来源于stack exchange,提问作者Régis Faria
相关产品推荐
相关产品推荐

