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

在MongooseModule.forFeatureAsync中注入UsersService失败排查

问题根源:循环依赖导致的DI解析失败

你这是典型的循环依赖问题:UsersService需要注入UserModel才能正常工作,但你创建UserModel的异步工厂函数又要注入UsersService——两者互相依赖,Nest的依赖注入容器根本无法确定初始化顺序,所以抛出了解析失败的错误。

解决方案

方案1:直接移除对UsersService的依赖(推荐)

Mongoose的pre('save')是文档中间件,钩子函数里的this指向当前要保存的User文档,完全可以直接操作文档本身,不需要通过UsersService中转。

修改后的MongooseModule配置如下:

MongooseModule.forFeatureAsync([
  {
    name: User.name,
    useFactory: () => {
      const schema = UserSchema;

      schema.pre('save', async function(next) {
        // 直接通过this访问当前文档,比如加密密码:
        // this.password = await bcrypt.hash(this.password, 10);
        next();
      });

      return schema;
    },
    // 删掉inject数组和useFactory的UsersService参数
  }
]),

方案2:抽离独立服务打破循环(若必须复用逻辑)

如果你的钩子逻辑确实需要复用现有代码,不要直接依赖UsersService,而是把公共逻辑抽成一个不依赖UserModel的独立服务,再在工厂函数中注入这个服务。

比如先创建一个工具服务:

@Injectable()
export class UserUtilsService {
  async hashPassword(password: string) {
    return bcrypt.hash(password, 10);
  }
}

然后在UsersModule中注册并注入这个服务:

@Module({
  controllers: [UsersController],
  exports: [UsersService],
  providers: [UsersService, UserUtilsService], // 注册独立工具服务
  imports: [
    forwardRef(() => AuthModule),
    MongooseModule.forFeatureAsync([
      {
        name: User.name,
        useFactory: (userUtils: UserUtilsService) => {
          const schema = UserSchema;

          schema.pre('save', async function(next) {
            this.password = await userUtils.hashPassword(this.password);
            next();
          });

          return schema;
        },
        inject: [UserUtilsService], // 注入独立服务而非UsersService
      }
    ]),
  ]
})
export class UsersModule {}

这样就打破了循环依赖链,Nest的DI容器可以正常解析所有服务和模型。

内容的提问来源于stack exchange,提问作者Brandon Taylor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 13:17:17