前端页面,有的筛选条件是radio单选框,用户便能快速并且多次点击。这样就会导致存在多个接口同时在请求,响应成功的顺序不确定(响应的时间不确定),就会导致最后一次点击响就回来的数据,可能会被之前点击响应回来的数据替换掉,或者会重复添加。所以在请求前,要先将之前的请求中断掉。
axios的config中提供了一个 AbortController(新)与cancelToken(旧)的属性来取消请求。下面有两种方式取消请求。
AbortController:从 v0.22.0 开始,Axios 支持以 fetch API 方式—— AbortController 取消请求。
CancelToken:此 API 从 v0.22.0 开始已被弃用,不应在新项目中使用。
AbortController方式:(推荐使用该方式)
注意:利用拦截器的config配置取消请求,请参数下面的CancelToken的示例。
const controller = new AbortController();
axios.get('/foo/bar', {
signal: controller.signal
}).then(function(response) {
//...
});
// 取消请求
controller.abort();
在过渡期间,您可以使用这两种取消 API,即使是针对同一个请求:
const controller = new AbortController();
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.get('/user/12345', {
cancelToken: source.token,
signal: controller.signal
}).catch(function (thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
// 处理错误
}
});
axios.post('/user/12345', {
name: 'new name'
}, {
cancelToken: source.token
})
// 取消请求 (message 参数是可选的)
source.cancel('Operation canceled by the user.');
// 或
controller.abort(); // 不支持 message 参数
=====================================================================================================================================
CancelToken方式一:利用拦截器的config配置取消请求cancelToken。
注:为了简单演示,所以用全局变量window.API_URL_REQUEST_LIST缓存取消请求函数,建议开发人员配置到Vuex、pinia等状态管理库中。
import axios from 'axios';
//声明全局变量,缓存(中断)函数
if(window.API_URL_REQUEST_LIST === undefined){
window.API_URL_REQUEST_LIST = [];
}
const service = axios.create({
//baseURL: '/jeecg-boot',
timeout: 9E3, // 请求超时时间9秒
});
//请求前,拦截器
service.interceptors.request.use(config => {
if(!config.cancelToken){//添加判断,允许用户使用方式二,否则方式二的cancelToken只会被替换
config.cancelToken = new axios.CancelToken(cancel => {
let obj = {
cancel:cancel,//cancel是个函数function
url:config.url,
cancelUuid:config.cancelUuid,
};
window.API_URL_REQUEST_LIST.push(obj);
});
}
return config;
}, (error) => {
return Promise.reject(error);
});
//响应后,拦截器
service.interceptors.response.use((response) => {
let {url,cancelUuid} = response.config.url;
window.API_URL_REQUEST_LIST.forEach((element,index) => {
if(element.url === url && element.cancelUuid === cancelUuid){
window.API_URL_REQUEST_LIST.splice(index, 1);//删除cancel函数
}
});
return response.data;
}, err);
//import { axios } from '**/**';//导出
export {
service as axios
}
Vue组件:按钮快速且多次点击,每次请求前都会中断之前的请求。
<template>
<button @click="getDataList">请频繁点击</button>
</template>
<script>
import { axios } from '**/**';//导出
export default {
name: 'Vue2',
data() {
return {
params: {
id: 888,
},
}
},
mounted() {
},
methods: {
getDataList(){
let url = '/apis/**/getById';
let cancelUuid = `uuid_${Date.now()}_${parseInt(Math.random() * 1E12)}`;//唯一标识
//中断请求
if(window.API_URL_REQUEST_LIST){
window.API_URL_REQUEST_LIST.forEach((element,index) => {
if(element.url === url && element.cancelUuid === cancelUuid){
let cancel = obj[url];
cancel();//中断函数执行
window.API_URL_REQUEST_LIST.splice(index, 1);//删除cancel函数
}
});
}
return axios({
url: url,
method: 'get',
params: this.params,
cancelUuid,
}).then(()=>{
//请求成功,这里执行
}).catch(()=>{
//中断请求,这里执行
});
}
},
}
</script>
====================================================================================================================================================
CancelToken方式二:将cancelToken直接写在axios({})参数内。
Vue组件:按钮快速且多次点击,每次请求前都会中断之前的请求。
<template>
<button @click="getDataList">请频繁点击</button>
</template>
<script>
import _Axios_ from 'axios';
import { axios } from '**/**';//导出
export default {
name: 'Vue2',
data() {
return {
params: {
id: 888,
},
}
},
mounted() {
},
methods: {
//写法1:
getDataList(){
//中断请求,写法1
if(this.sourceList === undefined){
this.sourceList = [];
}else{
this.sourceList.forEach(element => element.cancel('发起新请求了,中断之前的请求!'));// 取消请求(message 参数是可选的)
this.sourceList = [];
}
let source = _Axios_.CancelToken.source();
this.sourceList.push(source);
return axios({
url: '/apis/**/getById',
method: 'get',
params: this.params,
cancelToken:source.token,
}).then(()=>{
//请求成功,这里执行
}).catch(()=>{
//中断请求,这里执行
}).finally(()=>{
});
},
//写法2:
getDataList2(){
//中断请求,写法2
if(this.cancelList === undefined){
this.cancelList = [];
}else{
this.cancelList.forEach(element => element('发起新请求了,中断之前的请求!'));// 取消请求(message 参数是可选的)
this.cancelList = [];
}
return axios({
url: '/apis/**/getById',
method: 'get',
params: this.params,
cancelToken: new _Axios_.CancelToken(cancel=>{
this.cancelList.push(cancel);
}),
}).then(()=>{
//请求成功,这里执行
}).catch(()=>{
//中断请求,这里执行
}).finally(()=>{
});
},
},
}
</script>
参考链接:
https://www.npmjs.com/package/axios