模糊搜索,搜索框值改变后,网络不稳定等因素,导致返回的结果先后顺序不同

Jiafeng

分类: axios、Vue 0 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>

说明:

  1. 这里time为返回的延时时间,如:输入1000,1s后返回[1000,1001,1002],输入10000,10s后返回[10001,10002,10003]
  2. 如上图,最后输入的是10,应该显示的是[10,11,12],但是由于接口10s后才返回的[10001,10002,10003],导致显示的结果和输入的顺序不同

解决方法:

  1. 每次请求完成后记录请求开始的时间,待接口返回后比较前一次记录的时间和当前请求的时间,若前一次记录的时间大于当前时间,则不做处理,否则记录本次请求开始时间,options重新赋值。

    代码如下:

    
    
    
  2. 使用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人 Love
  • 0人 Haha
  • 0人 Wow
  • 0人 Sad
  • 0人 Angry
axios、select、Vuejs

作者简介: Jiafeng

共 0 条评论关于 “模糊搜索,搜索框值改变后,网络不稳定等因素,导致返回的结果先后顺序不同”

Loading...