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

NestJS+Cqrs+Fastify架构下注入REQUEST到SessionService失败求助

解决NestJS CQRS中请求作用域SessionService注入REQUEST为undefined的问题

核心问题在于:CQRS的CommandHandler默认是单例作用域,而你的SessionService是请求作用域。单例的CommandHandler无法直接访问请求上下文,导致通过ModuleRef.resolve获取的依赖链无法正确注入REQUEST。

解决方案步骤

1. 将请求上下文传递到Command中

修改你的Command类,添加request属性,让控制器能把当前请求传入:

export class SignInCommand {
  constructor(
    public readonly email: string,
    public readonly password: string,
    public readonly request: FastifyRequest // 新增请求属性
  ) {}
}

// SignOutCommand同理修改
export class SignOutCommand {
  constructor(
    public readonly email: string,
    public readonly request: FastifyRequest
  ) {}
}

2. 控制器中注入请求并传入Command

在控制器方法中通过@Req()装饰器获取当前请求,传入Command实例:

@Controller('sessions')
export class SessionController {
  constructor(private readonly commandBus: CommandBus) {}

  @Post()
  signIn(@Body() signInDto: SignInDto, @Req() request: FastifyRequest) {
    return this.commandBus.execute(
      new SignInCommand(signInDto.email, signInDto.password, request),
    );
  }

  @Delete()
  signOut(@Body() signOutDto: SignOutDto, @Req() request: FastifyRequest) {
    return this.commandBus.execute(new SignOutCommand(signOutDto.email, request));
  }
}

3. 在CommandHandler中传递请求上下文到ModuleRef

在execute方法里,从Command取出请求,通过ModuleRef.resolve的context参数传递请求上下文,确保请求作用域的依赖能正确获取REQUEST:

@CommandHandler(SignInCommand)
export class SignInCommandHandler implements ICommandHandler<SignInCommand> {
  constructor(
    private readonly moduleReference: ModuleRef,
  ) {}

  async execute(command: SignInCommand): Promise<Session> {
    const sessionUseCase = await this.moduleReference.resolve(SessionUseCase, {
      context: { request: command.request }, // 传递请求上下文
    });
    return await sessionUseCase.signIn(command.email, command.password);
  }
}

// SignOutCommandHandler同理修改
@CommandHandler(SignOutCommand)
export class SignOutCommandHandler implements ICommandHandler<SignOutCommand> {
  constructor(
    private readonly moduleReference: ModuleRef,
  ) {}

  async execute(command: SignOutCommand): Promise<void> {
    const sessionUseCase = await this.moduleReference.resolve(SessionUseCase, {
      context: { request: command.request },
    });
    return await sessionUseCase.signOut();
  }
}

4. 验证SessionService的注册配置

确保你的模块中正确注册了SessionService,并且映射到ISessionService令牌:

@Module({
  providers: [
    {
      provide: ISessionService,
      useClass: SessionService, // SessionService已设置Scope.REQUEST
    },
    SessionUseCase,
    SignInCommandHandler,
    SignOutCommandHandler,
    // 其他依赖...
  ],
  controllers: [SessionController],
})
export class SessionModule {}

关键原理说明

NestJS的请求作用域依赖需要请求上下文才能实例化,而CQRS的CommandBus默认执行单例CommandHandler,不会自动携带请求上下文。通过手动将请求从控制器传递到Command,再到ModuleRef.resolve时传入上下文,就能让请求作用域的SessionService正确获取到REQUEST实例。

内容的提问来源于stack exchange,提问作者Alessandro Aguilar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 22:35:25