前言
当事件中的代码执行耗费时间,且用户在短时间不断点击按钮,造成短时间多次触发了按钮的事件(不断向服务器发起请求)
在 vue 页面直接使用
代码如下(示例):
<script>
import axios from 'axios'
import qs from 'qs'
export default {
methods: {
request(keyword) {
var CancelToken = axios.CancelToken
var source = CancelToken.source()
// 取消上一次请求
this.cancelRequest();
// 有的人可能会出现415 400的错误,415是因为没有设置对Content-Type 400是因为使用了qs.stringify(), 可以修改成JSON.stringify() 试试
axios.post(url, qs.stringify({kw:keyword}), {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json'
},
cancelToken: new axios.CancelToken(function executor(c) {
that.source = c;
})
}).then((res) => {
// 在这里处理得到的数据
...
}).catch((err) => {
if (axios.isCancel(err)) {
console.log('Rquest canceled', err.message); //请求如果被取消,这里是返回取消的message
} else {
//handle error
console.log(err);
}
})
},
cancelRequest(){
if(typeof this.source ==='function'){
this.source('终止请求')
}
},
}
}
</script>
封装 utils 工具类
封装axios
请求,在响应拦截器中处理,结束上一次请求
步骤如下:
- 定义一个
Map
用来存储发送请求的取消【函数】标识。- 在请求拦截器中,移出重复的请求【重复请求是指:方法 + 路径 + 入参 相同】。
- 在请求拦截器中,发送请求前存储取消标识到
Map
中。- 在响应拦截器中,移出请求。
代码如下(示例):
import axios from "axios";
let pendingMap = new Map();
/**
* 取消正在发送的请求
* @param {*} config
*/
let removePending = function(config){
var key = `${config.method}:${config.url}:${JSON.stringify(config.params)}`;
var func = pendingMap.get(key);
if(func){
func();
pendingMap.delete(key);
}
}
// 创建axios实例
const baseURL = "/api";
const requests = axios.create({
baseURL:baseURL,
timeout:5000
});
//请求拦截器
requests.interceptors.request.use((config) =>{
removePending(config);
// config 中包含 headers 请求头
config.headers.Authorization = `Bear ${ sessionStorage.getItem("token")}`;
// 发送请求,并将请求的取消标识放入pendingMap中
config.cancelToken = new axios.CancelToken((cancelToken) => {
pendingMap.set(`${config.method}:${config.url}:${JSON.stringify(config.params)}`,cancelToken)
});
return config;
});
//响应拦截器
requests.interceptors.response.use((res) => {
// 请求成功移出请求
removePending(res.config);
return res.data;
},(error) => {
return Promise.reject(error);
});
export default requests;