Vuex中如何原子删除数组元素 解决取消订单后表格残留行问题
问题根因排查
首先你现有代码存在两个致命逻辑错误,这是导致表格行残留的核心原因,和并发问题叠加后现象更明显:
splice用法错误:Array.prototype.splice()会直接修改原数组,返回值是被删除元素组成的数组,你直接把返回值赋值给state.runningOrders.data,相当于执行删除后把原订单列表直接替换成了刚刚被删掉的那条订单数据,后续删除操作自然找不到对应id的订单,直接逻辑失效。- mutation中id未定义:你的mutation接收的参数是服务端返回的
res,但代码中直接使用了未声明的id变量,没有从参数中提取目标订单id,删除逻辑本身就无法正确执行。
原子(并发安全)删除实现方案
因为你批量触发的是多个异步取消请求,多个请求返回时机不确定,并发触发mutation修改数组时,依赖数组索引的splice方法天然不适用(前一个修改已经改变了数组长度/元素位置,后一个计算出的索引就会错位)。
推荐用filter方法实现无锁并发安全删除:filter是基于id做匹配过滤,不依赖数组的索引、长度、元素顺序,不管数组之前被其他操作修改过多少次,只要id唯一,就能准确过滤掉目标元素,完全避免并发修改冲突。
修正后代码
const actions = { async [CANCEL_ONE_ORDER](context, data) { const data_res = await RestClient.get("cancel_one_order", `${data.id}/${data.coin1}/${data.coin2}`); // 把原始目标id透传到mutation,避免服务端返回结果不含id的兼容性问题 context.commit(CANCEL_ONE_ORDER_END, { res: data_res.data, targetOrderId: data.id }); }, } const mutations = { [CANCEL_ONE_ORDER_END](state, payload) { // 直接过滤掉目标id的订单,生成新数组赋值给state,符合Vuex的响应式更新规则 state.runningOrders.data = state.runningOrders.data.filter(item => item.id !== payload.targetOrderId); }, }
可选优化(强并发控制)
如果你的取消请求并发量很高,想要严格控制执行顺序,可以加一层任务队列:
- 把所有选中要取消的订单id存入本地队列,按顺序逐个执行取消请求,前一个请求处理完成并更新state后,再执行下一个,从根源上避免并发修改场景。
内容的提问来源于stack exchange,提问作者YNX
相关产品推荐
相关产品推荐

