Logger依赖注入报错:Cannot read properties of undefined (reading 'Logger')
将Logger依赖注入MongoDBConnector时出现TypeError错误
当尝试将Logger依赖注入到MongoDBConnector类时,抛出以下错误:
E:\my_site\src\common\database\MongoDBConnector.ts:11 constructor(@inject(COMMON_TYPES.Logger) logger: ILogger) { ^TypeError: Cannot read properties of undefined (reading 'Logger') at Object.<anonymous> (E:\my_site\src\common\database\MongoDBConnector.ts:11:38) at Module._compile (node:internal/modules/cjs/loader:1469:14) at Module.m._compile (E:\my_site\node_modules\ts-node\src\index.ts:1618:23) at Module._extensions..js (node:internal/modules/cjs/loader:1548:10) at Object.require.extensions.<computed> [as .ts] (E:\my_site\node_modules\ts-node\src\index.ts:1621:12) at Module.load (node:internal/modules/cjs/loader:1288:32) at Function.Module._load (node:internal/modules/cjs/loader:1104:12) at Module.require (node:internal/modules/cjs/loader:1311:19) at require (node:internal/modules/helpers:179:18) at Object.<anonymous> (E:\my_site\src\common\common_injection_container.ts:4:1)
相关代码文件
inversify.config.ts
import { Container, ContainerModule } from 'inversify'; import { commonContainer, COMMON_TYPES } from '../common_injection_container'; import { ILogger } from '../../common/interfaces/ILogger'; const appContainer = new Container(); appContainer.load(commonContainer); const logger = appContainer.get<ILogger>(COMMON_TYPES.Logger); interface ContainerDefinition { container: ContainerModule; name: string; } const containers: ContainerDefinition[] = [ ]; containers.forEach(({ container, name }) => { try { appContainer.load(container); logger.info(`${name} container loaded successfully`); } catch (error) { logger.error(`Failed to load ${name} container`); if (error instanceof Error) { logger.trackError(error); } else { logger.error('An unknown error occurred while loading the container.'); } } }); export { appContainer };
common_injection_container.ts
import { ContainerModule, interfaces } from 'inversify'; import { ILogger } from './interfaces/ILogger'; import Logger from './utils/Logger'; import { MongoDBConnector } from './database/MongoDBConnector'; const COMMON_TYPES = { Logger: Symbol.for('Logger'), MongoDBConnector: Symbol.for('MongoDBConnector'), }; const commonContainer = new ContainerModule((bind: interfaces.Bind) => { bind<ILogger>(COMMON_TYPES.Logger).to(Logger).inSingletonScope(); bind<MongoDBConnector>(COMMON_TYPES.MongoDBConnector).to(MongoDBConnector); }); export { commonContainer, COMMON_TYPES };
MongoDBConnector.ts
import mongoose from 'mongoose'; import { inject, injectable } from 'inversify'; import { ILogger } from '../../common/interfaces/ILogger'; import { COMMON_TYPES } from '../../common/common_injection_container'; @injectable() export class MongoDBConnector { private logger: ILogger; constructor(@inject(COMMON_TYPES.Logger) logger: ILogger) { if (!logger) { throw new Error('Logger not found during MongoDBConnector injection'); } this.logger = logger; } public async connectToMongoDB(): Promise<void> { try { await mongoose.connect(process.env.MONGODB_URI!, { serverSelectionTimeoutMS: 30000, }); this.logger.info('Connected to MongoDB'); } catch (error: any) { if (error instanceof Error) { this.logger.error('Could not connect to MongoDB'); this.logger.error(`Error details: ${error.message}`); } else { this.logger.error('Could not connect to MongoDB with an unknown error'); } throw error; } } }
问题原因
错误源于循环模块导入:
common_injection_container.ts导入了MongoDBConnectorMongoDBConnector.ts又反向导入了common_injection_container.ts
Node.js加载模块时,会先处理common_injection_container.ts,此时它会触发MongoDBConnector的加载;而MongoDBConnector需要访问COMMON_TYPES.Logger,但此时COMMON_TYPES还未被common_injection_container.ts完成导出,导致COMMON_TYPES为undefined,最终抛出错误。
解决方案
方案1:拆分COMMON_TYPES到独立文件(推荐)
将类型定义从容器配置文件中分离,彻底避免循环引用:
- 创建
common_types.ts文件:
export const COMMON_TYPES = { Logger: Symbol.for('Logger'), MongoDBConnector: Symbol.for('MongoDBConnector'), };
- 修改
common_injection_container.ts:
import { ContainerModule, interfaces } from 'inversify'; import { ILogger } from './interfaces/ILogger'; import Logger from './utils/Logger'; import { MongoDBConnector } from './database/MongoDBConnector'; import { COMMON_TYPES } from './common_types'; const commonContainer = new ContainerModule((bind: interfaces.Bind) => { bind<ILogger>(COMMON_TYPES.Logger).to(Logger).inSingletonScope(); bind<MongoDBConnector>(COMMON_TYPES.MongoDBConnector).to(MongoDBConnector); }); export { commonContainer };
- 修改
MongoDBConnector.ts:
import mongoose from 'mongoose'; import { inject, injectable } from 'inversify'; import { ILogger } from '../../common/interfaces/ILogger'; import { COMMON_TYPES } from '../../common/common_types'; @injectable() export class MongoDBConnector { // 其余代码保持不变 }
- 修改
inversify.config.ts:
import { Container, ContainerModule } from 'inversify'; import { commonContainer } from '../common_injection_container'; import { COMMON_TYPES } from '../common_types'; import { ILogger } from '../../common/interfaces/ILogger'; // 其余代码保持不变
方案2:延迟导入(临时方案)
若不想拆分文件,可使用异步延迟导入MongoDBConnector,但会增加代码复杂度:
修改common_injection_container.ts:
import { ContainerModule, interfaces } from 'inversify'; import { ILogger } from './interfaces/ILogger'; import Logger from './utils/Logger'; const COMMON_TYPES = { Logger: Symbol.for('Logger'), MongoDBConnector: Symbol.for('MongoDBConnector'), }; const commonContainer = new ContainerModule(async (bind: interfaces.Bind) => { bind<ILogger>(COMMON_TYPES.Logger).to(Logger).inSingletonScope(); // 延迟导入MongoDBConnector const { MongoDBConnector } = await import('./database/MongoDBConnector'); bind<MongoDBConnector>(COMMON_TYPES.MongoDBConnector).to(MongoDBConnector); }); export { commonContainer, COMMON_TYPES };
同时修改inversify.config.ts的容器加载方式:
// 替换原加载代码 await appContainer.loadAsync(commonContainer);
内容的提问来源于stack exchange,提问作者NoBody
相关产品推荐
相关产品推荐

