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
相关产品推荐
相关产品推荐

