高频输入终止上一次请求

554 阅读2分钟

问题:input输入框频繁请求接口,如何正确的显示最后一次返回的结果

搜索框功能,还是边输入边搜索边展示结果,会出现接口返回结果比较慢或者是多次请求中有的接口返回结果比最后一次返回结果要慢,导致最终结果不是最新结果

解决方法:

第一种:后端协助处理

后端协助处理,返回请求值(前端通过接口的时候会把input输入的值传给后台,后台返回的时候把前端传入的值再回传回来,前端页面渲染的时候进行判断返回的值与页面的值是否一致即可)

缺点:需要后端的参与

第二种:终止上一次的请求

  • ajax: abort()
  • axios: CancelToken
  • fetch:AbortController
import axios from 'axios';
import request from '@/utils/request'
let CancelToken = axios.CancelToken;
window.cancle = null
export const queryResourceTable = function (params) {
    return request({
        url: '/remote/getResourceList',
        method: 'get',
        params,
        cancelToken:new CancelToken(function executor(c) { 
            window.cancle = c;
        })
    });
};
import { queryResourceTable } from '@/api/index'
async getData(){
     // 取消上一次请求
     window.cancle && window.cancle()
     let data  = await queryResourceTable()
}

这样的话我们每次调用这个接口,如果上次或者上上次调用因为网络延时或者接口请求慢还没有响应,就会取消,重新发起一个新的请求,就不会出现开始说的那个问题
如果一个项目中有多个接口需要取消上次请求,那么我们只需要给window上挂载一个属性统一管理

import axios from 'axios';
import request from '@/utils/request'
let CancelToken = axios.CancelToken;
window.cancle = {}
export const queryResourceTable = function (params) {
    return request({
        url: '/remote/getResourceList',
        method: 'get',
        params,
        cancelToken:new CancelToken(function executor(c) { 
            window.cancle.resourceTable = c;
        })
    });
};
// 调用
window.cancle.resourceTable && window.cancle.resourceTable()

通过Promise.race()优化

this.cancel = () => {};
function fetchResult() { // input输入事件
   this.cancel(); // 高频率输入时取消上一个请求
   const abortRequest = new Promise(resolve => this.cancel = resolve);
   Promise.race([abortRequest, 请求接口的Promise对象)]).then(ret => {
      // 判断请求结果 如果是因为高频取消上一个请求的话this.cancel()并没有传值
      if (ret) {
        // 请求结果
      }
   });
}

第三种:全局 ID控制

第三种方法:定义一个全局 ID,接口请求之前自增,然后请求接口闭包保存此值,返回之后进行两者判断

优化:

防抖+loading结合