Angular NgRx 12中如何用withLatestFrom处理依赖式多Observable?
解决方案:NgRx Effect 中依赖其他Selector结果的动态Selector调用
你当前的写法没法直接实现,因为formData.someValue在withLatestFrom的参数列表里还未被获取,此时formData是未定义的变量。要实现这种依赖其他Selector结果的动态Selector调用,可以通过嵌套流操作来处理,下面是两种可行的实现方式:
方法一:用switchMap + withLatestFrom 分步获取
switchMap((action: Action) => this.store.pipe( select(fromA.getFormData), take(1), // 仅获取当前Store中的formData值,避免持续监听 withLatestFrom( this.store.pipe(select(fromA.getFiles)), (formData) => this.store.pipe(select(fromB.isLoading(formData.someValue))) ), map(([formData, files, isLoading]) => ({ formData, files, isLoading })) ) ), mergeMap(({ formData, files, isLoading }) => { // 这里可以使用所有获取到的数据执行后续逻辑 // ... })
逻辑说明:
- 先用
switchMap接收触发Effect的Action,进入后续的Store查询流 - 先获取
formData的值,通过take(1)确保只取当前状态(而非持续监听变化) - 在
withLatestFrom中,先获取files,再通过回调函数动态传入formData.someValue到isLoadingSelector中,获取对应的状态 - 最后将所有数据映射成一个对象,传递给后续的
mergeMap
方法二:用嵌套switchMap + combineLatest 组合多流
switchMap((action) => { return this.store.pipe( select(fromA.getFormData), take(1), switchMap((formData) => { // 拿到formData后,组合所有需要的Selector流 return combineLatest([ of(formData), // 将formData包装成Observable,方便组合 this.store.pipe(select(fromA.getFiles)), this.store.pipe(select(fromB.isLoading(formData.someValue))) ]); }), map(([formData, files, isLoading]) => ({ formData, files, isLoading })) ); }), mergeMap((data) => { // 处理业务逻辑 // ... })
逻辑说明:
- 第一步同样先获取
formData - 在内部的
switchMap中,使用combineLatest将formData(包装为Observable)、files、依赖formData的isLoading状态流组合起来 - 映射成统一的数据对象后传递给后续操作
注意事项:
- 如果需要监听
formData或其他状态的持续变化,可以去掉take(1),但Effect通常只需要响应Action触发时的当前状态,所以take(1)是更常见的用法 - 确保
fromB.isLoading是一个工厂Selector(即接收参数并返回Selector函数的类型),否则无法动态传入参数
内容的提问来源于stack exchange,提问作者Daniel W
相关产品推荐
相关产品推荐

