Angular14:Observable<number>转number及购物车删除异常问题
Angular NgRx 问题解决:类型错误与数组操作异常
一、Dispatch时的类型错误问题
问题场景
组件调用getBasket action时触发类型错误:type Observable<number> isn't assignable to number。
组件代码:
constructor(private store: Store, private basketStore: Store<{ basket: Photo[] }>) { } position$! :Observable<number>; RemoveFromBasket(photo: Photo) { this.position$ = this.basketStore.select(basketPosition(photo.id)); this.basketStore.dispatch(getBasket({ id: this.position$})); }
问题原因
basketStore.select()返回的是Observable<number>类型的数据流,但getBasket action的id参数需要原始number类型,直接传递Observable会触发类型不匹配。
解决方案
订阅Observable获取实际数值后再dispatch action,同时用take(1)避免内存泄漏:
import { take } from 'rxjs/operators'; RemoveFromBasket(photo: Photo) { this.basketStore.select(basketPosition(photo.id)) .pipe(take(1)) .subscribe(position => { // 确保索引有效再执行 if (position !== -1) { this.basketStore.dispatch(getBasket({ id: position })); } }); }
二、数组Slice操作导致的异常问题
问题场景
修复类型错误后,删除购物车中重复ID的商品时出现异常:
- 使用
state.slice(id)时,会移除索引id之前的所有元素 - 修改为
state.slice(id,1)时,购物车被直接清空
原reducer代码:
on(getBasket, (state, { id }) => state.slice(id)
问题原因
数组slice()方法的参数是(startIndex, endIndex),作用是截取指定区间的元素并返回新数组,并非删除指定位置元素:
state.slice(id):返回从索引id到数组末尾的元素,相当于保留后半部分、删除前半部分state.slice(id,1):当id >=1时,起始索引大于结束索引,返回空数组
解决方案
要删除指定索引的元素,需使用正确的数组操作逻辑,以下两种方案均可:
方案1:扩展运算符+slice组合
on(getBasket, (state, { id }) => { // 索引无效时直接返回原状态 if (id < 0 || id >= state.length) return state; // 合并目标索引前后的元素,跳过要删除的项 return [...state.slice(0, id), ...state.slice(id + 1)]; });
方案2:复制数组后使用splice
on(getBasket, (state, { id }) => { const newBasket = [...state]; if (id >= 0 && id < newBasket.length) { // 从索引id开始删除1个元素 newBasket.splice(id, 1); } return newBasket; });
内容的提问来源于stack exchange,提问作者bilpor
相关产品推荐
相关产品推荐

