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

NestJS CQRS 中QueryHandler的Repository等依赖注入失败如何解决

NestJS CQRS 请求作用域依赖注入失败解决方案

问题现象

实现CQRS模式时,@QueryHandler修饰的类中所有注入的依赖均为undefined,执行方法时触发如下报错:

UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'getCustomer' of undefined at CustomerHandler.execute 

相关代码参考

1. Request作用域业务服务

@Injectable({scope: Scope.REQUEST})
export class CustomerService {
  constructor(
    @Inject(REQUEST) private readonly req: Request,
    private readonly queryBus: QueryBus,
  ) {}
}

2. Query 处理器定义

@QueryHandler(CustomerQuery)
export class CustomerHandler implements IQueryHandler<CustomerQuery> {
  constructor(
    private readonly repository: CustomerRepository,
  ) {}

  async execute(query: CustomerQuery) {
    const {response, id, name} = query;
    this.repository.getCustomer(response, id, name);
  }
}

3. 模块配置

@Module({
  imports: [Logger, CqrsModule],
  providers: [CustomerService, ...QueryHandlers, CustomerRepository],
  exports: [CustomerService],
})
export class CustomerModule {}

4. Repository 定义(注入了REQUEST对象)

@Injectable()
export class CustomerRepository {
  constructor(
    @Inject(REQUEST) private readonly req: Request,
  ) {}
}

根因说明

CqrsModule的所有Provider均为静态作用域,底层设计不支持依赖请求作用域的Provider。如果Handler或者其依赖注入了REQUEST这类请求作用域的对象,会导致Handler的依赖注入链路失效。该问题是Cqrs模块的已知设计限制,非代码Bug。

可行解决方案

方案1:透传请求上下文(推荐,性能损耗最低)

取消在Handler及其依赖中注入REQUEST对象,将请求上下文通过Query的payload透传:

  • 修改Query定义,新增请求上下文参数
  • 业务服务调用QueryBus时传入当前请求对象
this.queryBus.execute(new CustomerQuery(this.req, response, id, name))
  • Handler执行时取出请求上下文,传入Repository方法
async execute(query: CustomerQuery) {
  const {req, response, id, name} = query;
  this.repository.getCustomer(req, response, id, name);
}
  • 调整Repository定义,移除REQUEST注入
@Injectable()
export class CustomerRepository {
  getCustomer(req: Request, response: any, id: string, name: string) {
    // 业务逻辑实现
  }
}

方案2:动态获取请求作用域实例

如果必须保留Repository的REQUEST注入,可以通过ModuleRef在执行阶段动态解析实例:

  • Handler中注入ModuleRef,执行时通过上下文ID解析依赖
@QueryHandler(CustomerQuery)
export class CustomerHandler implements IQueryHandler<CustomerQuery> {
  constructor(private readonly moduleRef: ModuleRef) {}

  async execute(query: CustomerQuery) {
    const {contextId, response, id, name} = query;
    // 动态解析请求作用域的Repository实例
    const repository = await this.moduleRef.resolve(CustomerRepository, contextId, { strict: false });
    repository.getCustomer(response, id, name);
  }
}
  • 业务服务调用QueryBus时传入当前请求的上下文ID
const contextId = ContextIdFactory.getByRequest(this.req);
this.queryBus.execute(new CustomerQuery(contextId, response, id, name))

内容的提问来源于stack exchange,提问作者s.k

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 12:36:04