乐趣区

axios重复点击取消上一次请求封装

使用场景

重复点击或者多 tab 标签使用一个视图等(当然也可以用加载中或者透明背景禁止请求中再次点击)

封装代码

来自于互联网

let pending = []; // 声明一个数组用于存储每个请求的取消函数和 axios 标识
let cancelToken = axios.CancelToken;
let removePending = (config) => {for(let p in pending){if(pending[p].u === config.url + '&' + config.method) { // 当当前请求在数组中存在时执行函数体
            pending[p].f(); // 执行取消操作
            pending.splice(p, 1); 
        }
    }
}



// http 请求拦截器
axios.interceptors.request.use(config => {removePending(config); // 在一个 axios 发送前执行一下取消操作
    config.cancelToken = new cancelToken((c)=>{
        // 这里的 axios 标识我是用请求地址 & 请求方式拼接的字符串,当然你可以选择其他的一些方式
        pending.push({u: config.url + '&' + config.method, f: c});  
    });
    
    return Promise.resolve(config)
}, error => {return Promise.reject(error)
})

// http 响应拦截器
axios.interceptors.response.use(data => {removePending(data.config);  // 在一个 axios 响应后再执行一下取消操作,把已经完成的请求从 pending 中移除
    
    return Promise.resolve(data)
    
}, error => {
    // 加载失败
    return {'data':{}}
    // return Promise.reject(error)
})

经过多次测试发现不同请求也给我取消了,原因是没有校验请求参数,也就是说 get 请求可以用,修改以下代码

pending.push({u: config.url + '&' + config.method, f: c}); 

修改为:

pending.push({u: config.url + JSON.stringify(config.data) +'&' + config.method, f: c });//config.data 为请求参数

上面判断也需要修改,这样 get 请求和 post 都可以用了

解决分析

(个人理解)
官方提供了 axios.CancelToken 来取消上一次请求方法,因此只需要判断上一次请求是否重复。声明数组变量 pending用于存储每个请求实例的 axios 标识(请求方式,请求参数,请求 url)和该实例的取消函数;在请求拦截器中创建取消函数实例,将请求的标识(判断重复标识)及 该请求实例取消函数 pushpending 数组中,创建取消上一次请求方法 removePending,该方法主要判断 axios 请求标识是否重复,重复则执行该实例的取消函数,并且从 pending中移除标识及该实例取消函数。

退出移动版