vue-infinite-loader结合姓名筛选时出现重复条目及错误数据的问题解决请求
解决Vue Infinite Loader筛选时请求并行导致的数据重复问题
这个问题的核心是多个异步请求无序返回——哪怕加了防抖,当请求耗时超过防抖间隔时,旧请求还是可能晚于新请求返回,导致数据混乱。解决的关键是在发起新请求前,主动取消掉之前未完成的请求,Axios自带的CancelToken正好能搞定这个需求。
下面是具体的实现步骤:
1. 初始化CancelToken源
在组件的data中添加变量,用于存储CancelToken的源:
data() { return { name: '', parameter: '', page: 1, users: [], infiniteId: 0, cancelTokenSource: null, // 存储请求取消令牌的源 timeout: null // 防抖定时器 } }
2. 修改请求方法,添加请求取消逻辑
在infiniteHandler里,每次发起新请求前先检查是否有未完成的请求,如果有就取消它,再创建新的CancelToken绑定到当前请求:
infiniteHandler: function ($state) { // 先取消之前未完成的请求 if (this.cancelTokenSource) { this.cancelTokenSource.cancel('请求被取消,因为发起了新的筛选/滚动加载'); } // 创建新的CancelToken源 this.cancelTokenSource = axios.CancelToken.source(); axios.get(api + this.parameter, { params: { page: this.page }, cancelToken: this.cancelTokenSource.token // 绑定取消令牌到当前请求 }).then((result) => { if (result.data.meta.current_page <= result.data.meta.last_page) { this.page += 1; this.users.push(...result.data.data); $state.loaded(); } else { $state.complete(); } }).catch((thrown) => { // 捕获取消请求的错误,无需额外处理 if (axios.isCancel(thrown)) { console.log('请求已取消:', thrown.message); } else { // 处理其他网络错误 $state.error(); } }); }
3. 优化changeName方法,结合防抖+请求取消
把防抖和请求取消结合,既减少不必要的请求次数,又能确保旧请求被及时终止:
changeName() { // 先取消之前未完成的请求 if (this.cancelTokenSource) { this.cancelTokenSource.cancel('筛选条件变更,取消旧请求'); } // 清空之前的防抖定时器 clearTimeout(this.timeout); this.timeout = setTimeout(() => { this.parameter = '?name=' + encodeURIComponent(this.name); this.page = 1; this.users = []; this.infiniteId += 1; // 触发infinite-loader重新加载数据 }, 200); }
额外优化:组件销毁时清理请求
为了避免内存泄漏,在组件销毁前记得取消未完成的请求:
beforeDestroy() { if (this.cancelTokenSource) { this.cancelTokenSource.cancel('组件销毁,取消未完成的请求'); } clearTimeout(this.timeout); }
为什么这样有效?
- 每次发起新请求(筛选或滚动加载),都会先终止之前未完成的请求,确保只有最新的请求结果能更新数据。
- 防抖逻辑减少了用户快速输入时的请求次数,避免无意义的接口调用。
- 即使防抖间隔内有多次输入,最终只会发起一次请求,且所有旧请求都被提前取消,彻底解决了旧请求返回干扰数据的问题。
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

