Angular组件中如何仅获取NGRX Action返回的第一个值?
核心说明
NGRX的actions是全局共享的热流,直接用take(1)可能会捕获到本次dispatch之前产生的同类型action,得到错误的响应结果,这也是相关规则禁用该写法的核心原因。
推荐方案:基于race操作符+请求唯一ID实现
这个方案既符合NGRX规范,也能保证仅消费本次请求对应的响应,无需手动管理订阅销毁:
- 首先改造三个Action,给
UpdateRequest添加唯一requestId字段,UPDATE_SUCCESS、UPDATE_ERROR响应Action都带回对应请求的requestId用于匹配。 - 组件内代码实现:
import { race } from 'rxjs'; import { filter } from 'rxjs/operators'; import { v4 as uuidv4 } from 'uuid'; // 生成本次请求的唯一标识 const requestId = uuidv4(); // 触发请求 this.store.dispatch(new UpdateRequest({ data, requestId })); // 组合成功、失败流,哪一个先触发就消费哪一个,流自动结束 race( this.actions.pipe( ofType(ActionTypes.UPDATE_SUCCESS), filter(action => action.requestId === requestId) ), this.actions.pipe( ofType(ActionTypes.UPDATE_ERROR), filter(action => action.requestId === requestId) ) ) .pipe(takeUntil(this.destroy$)) .subscribe(action => { if (action.type === ActionTypes.UPDATE_SUCCESS) { this.update(); } else { this.error(); } });
方案优势:
- 无需手动调用
unsubscribe,race操作符会在任意一个流触发后自动终止整个组合流,不会产生内存泄漏 - 唯一ID匹配确保不会捕获到其他请求产生的同类型Action,彻底解决
take(1)的不安全问题 - 仅会消费一次对应请求的响应结果,完全符合需求
简化方案(适用于单请求场景)
如果你能保证同一时间组件内只会发起一个UpdateRequest请求,不会有并发场景,可以不用加唯一ID,简化为:
this.store.dispatch(new UpdateRequest(data)); race( this.actions.pipe(ofType(ActionTypes.UPDATE_SUCCESS)), this.actions.pipe(ofType(ActionTypes.UPDATE_ERROR)) ) .pipe(takeUntil(this.destroy$)) .subscribe(action => { action.type === ActionTypes.UPDATE_SUCCESS ? this.update() : this.error(); });
这个方案也符合NGRX规范,不会触发相关规则校验。
内容的提问来源于stack exchange,提问作者deepdeer
相关产品推荐
相关产品推荐

