如何在NgRx Effect中组合两个选择器并获取状态值?
问题解答
可行性说明
同时执行这两个选择器完全可行,你代码里用到的withLatestFrom操作符,本身就是RxJS用来合并多个Observable当前值的工具,正好适合用来组合这两个Store选择器的数据流。
状态值获取方法
你当前的代码已经能正确获取两个选择器的返回值,不过可以调整写法让逻辑更清晰:
现有代码的取值逻辑
在mergeMap的参数解构里,[, transactionId, authPayload]就是对应的值:
- 第一个空占位符对应的是
of(action)输出的action对象(你用of(action).pipe(withLatestFrom(...))把action流和两个选择器流合并了) transactionId就是getTransactionIDSelector的状态值authPayload就是getAuthPayload的状态值
简化优化写法(可选)
如果不需要用到原始的action对象,完全可以去掉of(action)这一层,直接合并两个选择器:
concatMap(() => this.store.pipe( withLatestFrom( this.store.select(getTransactionIDSelector), this.store.select(getAuthPayload) ) )), mergeMap(([, transactionId, authPayload]) => { // 第一个参数是根Store状态,不需要就用占位符跳过 // 后续调用服务的逻辑不变 })
还有更简洁的写法,直接把withLatestFrom放在主管道里,不用嵌套concatMap:
getJwtToken$ = createEffect(() => { return this.actions$.pipe( ofType(TransactionIDActionTypes.LOAD_SUCCESS), withLatestFrom( this.store.select(getTransactionIDSelector), this.store.select(getAuthPayload) ), mergeMap(([action, transactionId, authPayload]) => { // action是触发当前effect的LOAD_SUCCESS动作对象 // transactionId和authPayload分别对应两个选择器的状态值 return this.authenticationService.getJwtToken(this.AuthenticateRequest(transactionId, authPayload)).pipe( map(response => LoadSessionSuccess(response)), catchError(error => of(LoadSessionError(error))) ); }) ); });
补充:AuthenticateRequest的参数完善
看你的AuthenticateRequest方法需要多个属性,这些属性应该都来自authPayload,所以要把authPayload传进去,从中提取对应字段:
AuthenticateRequest(transactionId: string, authPayload: any): AuthenticateInterface { return { transactionId, sourceIdentifier: authPayload.sourceIdentifier, residentType: authPayload.residentType, organizationCode: authPayload.organizationCode, profile: authPayload.profile, kycId: authPayload.kycId, identificationNumber: authPayload.identificationNumber, mobileIdentifier: authPayload.mobileIdentifier, nationality: authPayload.nationality, dateAcceptedTermsOfUse: authPayload.dateAcceptedTermsOfUse, }; }
注意事项
- 要确保两个选择器能正确从Store中取到对应状态,避免返回
undefined——可以在选择器内部添加默认值处理 withLatestFrom要求所有传入的Observable至少发出过一次值才会继续执行,如果某个选择器对应的状态还没初始化,会导致Effect卡住,所以要保证触发LOAD_SUCCESS动作前,这两个状态已经存在
内容的提问来源于stack exchange,提问作者nhoyti
相关产品推荐
相关产品推荐

