模糊搜索,搜索框值改变后,网络不稳定等因素,导致返回的结果先后顺序不同
分类: axios、Vue 484 0
这里使用element-plus的el-select组件远程搜索为例,代码如下:
- delayedV1接口根据输入的时间进入延时返回
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { delayedV1 } from '@/api/test'
interface ListItem {
key: string
label: string
}
const options = ref<ListItem[]>([])
const value = ref<string[]>([])
const loading = ref(false)
const remoteMethod = async (query: number) => {
if (query) {
loading.value = true
let res: any = await delayedV1({time: query})
loading.value = false
options.value = res
} else {
options.value = []
}
}
</script>
<template>
<div>
<el-select v-model="value" multiple filterable remote reserve-keyword placeholder="Please enter a keyword"
:remote-method="remoteMethod" :loading="loading">
<el-option v-for="item in options" :key="item.key" :label="item.label" :value="item.key" />
</el-select>
</div>
</template>
说明:
- 这里time为返回的延时时间,如:输入1000,1s后返回[1000,1001,1002],输入10000,10s后返回[10001,10002,10003]
- 如上图,最后输入的是10,应该显示的是[10,11,12],但是由于接口10s后才返回的[10001,10002,10003],导致显示的结果和输入的顺序不同
解决方法:
-
每次请求完成后记录请求开始的时间,待接口返回后比较前一次记录的时间和当前请求的时间,若前一次记录的时间大于当前时间,则不做处理,否则记录本次请求开始时间,options重新赋值。
代码如下:
-
使用CancelToken,CancelToken是axios用来取消请求的API,官方文档,这里我们如何在项目中应用来取消重复的请求呢?
-
我们这里对cancelToken进行封装,创建一个Map集合,键为请求的信息(url,methods,params,data),值为对应的new axios.CancelToken构造函数创建的取消令牌
-
在axios请求拦截器中,对请求进行处理,先进行删除操作,再添加到Map集合
-
对需要单独CancelToken处理的接口进行区分,在请求头信心中添加headers: {cancel: true}
代码如下:
// request.ts import requestCancel from './requestCancel'; service.interceptors.request.use( (config) => { requestCancel.removePending(config); return requestCancel.addPending(config); }, (error) => { return Promise.reject(error); } );
// requestCancel.ts import axios from 'axios'; let pendings = new Map(); // 添加请求 const addPending = (config:any) => { const {url,methods,params,data,headers} = config; const id = headers.cancel ? [url,methods].join('&') : [url,methods,JSON.stringify(params),JSON.stringify(data)].join('&'); const cancel = pendings.has(id); config.cancelToken = config.cancelToken || new axios.CancelToken(c => { if(!cancel){ // 不存在,就存进去 pendings.set(id, c) } }) return config; } // 删除请求 const removePending = (config:any) => { const {url,methods,params,data,headers} = config; const id = headers.cancel ? [url,methods].join('&') : [url,methods,JSON.stringify(params),JSON.stringify(data)].join('&'); const cancel = pendings.has(id); const cancelFun = pendings.get(id); if(cancel && typeof cancelFun == 'function'){ // 存在这个请求,删除 cancelFun(); pendings.delete(id); } } // 清除所有请求 const clearPendings = () => { pendings.forEach((c: () => Function) => c()) } export default{ addPending,removePending,clearPendings}
// test.ts /** * 延时接口 * @returns */ export function delayedV1(params: {time: number}) { return request({ url:
${URL}/delayed/v1
, method: 'get', params, headers: {cancel: true} }) } -
同理,CancelToken还可用于菜单的路由页面跳转、tab栏的高频切换。页面切换取消上个页面的请求。可搭配vue-router使用
router.afterEach(() => {
// 清除上个页面未完成的请求
requestCancel.clearPendings();
});
共 0 条评论关于 “模糊搜索,搜索框值改变后,网络不稳定等因素,导致返回的结果先后顺序不同”