问题描述
我一直在使用 sequelize-typescript
、tsyringe
进行重构工作,在这里我发现了一个非常有趣的错误。
通常,我的所有存储库容器都在正常注册并使用以下设置正确实例化:
-
我将反射元数据导入到我的应用程序根目录及其后的
tsyringe
容器import 'reflect-Metadata'; import 'dotenv/config'; import express,{ Request,Response,NextFunction } from 'express'; ... import '@shared/infra/sequelize/index'; // default sequelize connection import '@shared/container/index';
-
容器/索引内部是以下代码,我使用
sequelize-typescript
制作存储库。import { container } from 'tsyringe'; import IUsersRepository from '@modules/users/repositories/IUsersRepositories'; import UsersRepository from '@modules/users/infra/sequelize/repositories/UserRepository'; ... import IModelRepository from '@modules/model/repositories/IModelRepository'; import ModelRepository from '@modules/model/infra/sequelize/repositories/ModelRepository'; container.registerSingleton<IUsersRepository>( 'UsersRepository',UsersRepository,); ... container.registerSingleton<IModelRepository>( 'ModelRepository',ModelRepository,);
-
然后我用 express 完成所有的路由:
import { Router } from 'express'; import bdDecider from '@shared/infra/http/middlewares/bdDecider'; import ensureAuthenticated from '@modules/users/infra/http/middlewares/EnsureAuthenticated'; import UserRouter from '@modules/users/infra/http/routes/user.routes'; ... import ModelRouter from '@modules/model/infra/http/routes/model.routes'; const routes = Router(); routes.use('/sessions',SessionRouter); routes.use(ensureAuthenticated); routes.use(bdDecider); //bdDecider as it says gets the logged on user bdConfig so i can connect to it routes.use('/model',ModelRouter);
-
所以我们去调用
的路由container.resolve()
import { container } from 'tsyringe'; import { Response,Request } from 'express'; import ShowModelsService from '@modules/invoices/services/ShowModelsService'; export default class ShowModelsController { public async show(req: Request,res: Response): Promise<Response> { const { id } = req.params; const showModelsService = container.resolve( //it calls the model service ShowModelsService,); const models = await showModelsService.execute( id,); return res.json(models); } }
-
这是他调用的服务
import IModelRepository from '@modules/model/repositories/IModelRepository'; import AppError from '@shared/errors/AppError'; import { inject,injectable } from 'tsyringe'; import IModelDTO from '../dtos/IModelDTO'; type IResponse = IModelDTO; @injectable() export default class ShowModelService { constructor( @inject('ModelRepository') private modelRepository: IModelRepository,) {} public async execute(id: string): Promise<IResponse> { const model = await this.modelRepository.get_models( id,); if (!model) { throw new AppError('Model not found!',404); } return model; } }
-
直到那里一切正常并且工作正常,但是当我尝试使用
sequelize
将该模型与另一个模型相关联时。Tsyringe
停止能够正确注入依赖项并给出标题错误消息。这是我试图关联的模型。import Model from '@modules/model/infra/sequelize/entities/Model'; import { DataTypes } from 'sequelize'; import { Sequelize } from 'sequelize-typescript'; import User from '../entities/User'; export default (sequelize: Sequelize): void => { Model.init( { primary: { allowNull: false,autoIncrement: true,primaryKey: true,type: DataTypes.INTEGER,},camp1: DataTypes.DECIMAL(20,2),camp2: DataTypes.DATE,{ tableName: 'tbl_model',sequelize,); Model.hasMany(User); }
-
如果我删除“
Model.hasMany(User);
”,它会恢复正常并发生注入,我很困惑不知道发生了什么...... -
顺便说一下,这里是我的模型存储库
import IModelRepository from '@modules/model/repositories/IModelRepository'; import AppError from '@shared/errors/AppError'; import { connection } from '@shared/infra/http/middlewares/bdDecider'; import { Repository } from 'sequelize-typescript'; import IModelDTO from '@modules/model/dtos/IModelDTO'; import initModel from '../utils/initInvoice'; import initUser from '../utils/initItem'; import Model from '../entities/Model'; import User from '../entities/User'; export default class ModelRepository implements IModelRepository { private ormRepository: Repository<Model>; constructor() { if (!connection) { throw new AppError( `You don't have a client settled on your user credentials or you don't have a client settled or both`,); } initModel(connection); // it Model.init() the model with the hasmany association initUser(connection); // it User.init() this.ormRepository = connection.getRepository(Model); } public async get_models( id: string,): Promise<IModelDTO | null> { const models = await this.ormRepository.findOne({ where: { id },include: [ { model: User,],}); return models; } }
-
如果信息太多,我很抱歉,但我尝试提供尽可能多的信息,以便有人可以帮助我..但老实说,我对找到解决方案有点怀疑,可能我会必须将此方法与此模型分离并尝试单独执行。正如您所注意到的,我更改了模型的名称,因此我可能拼错了某些内容,但不要担心实际代码中没有拼写错误,因为此错误仅在我将“
Model.hasMany(User);
”添加到 {{1 }} 功能。希望有人能够帮助我,我会在附近的任何问题不要害怕问。 :)
解决方法
哦,我想出了一个解决方案。最好在调用 container.resolve()
之前初始化模型。出于某种原因,当您尝试在其中初始化模型时,它看起来像是丢失了引用并且无法注入。但现在一切都很好:)
constructor() {
if (!connection) {
throw new AppError(
`You don't have a client settled on your user credentials or you don't have a client settled or both`,);
}
initModel(connection);
initUser(connection);
this.ormRepository = connection.getRepository(Model);
}
所以我只是从存储库构造函数中删除了 initModel 和 initUser 函数,并将其放在调用 container.resolve()
之前的其他位置。