文章目录
场景
用户在进行新增操作(比如新增菜单)。如果快速点击多次新增按钮,可能照成的情况就是新增了多条记录。一般可以通过在点击的时候,先禁用新增按钮,然后等本次操作完了,再解除禁用。不过,使用axios有更加优雅的实现方式。
axios防重复提交
思路
先说下思路:在进行axios提交操作的时候,把本次请求做一个标记,保存到一个数组中。等请求结束了,就从这个数组中,移除请求标记。所以,如果有两个完全一样的请求过来,那么后来的请求,就会发现在这个数组中,已经有了该标记,那么就在axios中取消本次请求。
具体实现
在我的代码中,已经对axios进行了统一的封装在http.js中了,所以,只需要在http.js中实现就好了:
首先定义一个数组来存请求标记,以及定义一个取消axios请求的对象:
// 请求列表(防重复提交)
let requestList = [];
let cancelToken = axios.CancelToken;
然后确定请求标记:这里我采用的就是请求的url+请求参数+请求方式,组合成一个字符串,作为请求标记,在request拦截器中,代码如下:
axios.interceptors.request.use(
config => {
//防止重复提交(如果本次是重复操作,则取消,否则将该操作标记到requestList中)
config.cancelToken = new cancelToken((cancel) => {
let requestFlag = JSON.stringify(config.url) + JSON.stringify(config.data) + '&' + config.method;
if (requestList.includes(requestFlag)) {//请求标记已经存在,则取消本次请求,否则在请求列表中加入请求标记
cancel();//取消本次请求
} else {
requestList.push(requestFlag);
}
});
return config;
},
error => {
return Promise.reject(err);
}
);
最后,在请求结束中,请请求标记移除,在response拦截器中,代码如下:
axios.interceptors.response.use(
response => {
//请求返回后,将请求标记从requestList中移除
let requestFlag = JSON.stringify(response.config.url) + JSON.stringify(response.config.data) + '&' + response.config.method;
requestList.splice(requestList.findIndex(item => item === requestFlag), 1);
return response;
},
error => {
//置空请求列表
requestList.length = 0;
return Promise.reject(error)
}
)
补充
如果在系统中,真的存在这种两个请求的url、参数、请求方式都一模一样,并且还要在用户的一个操作中向后端请求(我倒是没有遇到过这种情况),这个方式也是有解决方案的。在上面介绍中,请求标记,使用的方式是:url+请求参数+请求方式。那么这个时候在请求参数中,在加一个特别的参数就可以了,当然这个参数只是为了防止重复提交中,请求标记的确定,并没有其他作用。当然,也可以另想一个办法来实现这个请求标记。总之,这种需求,几乎不会出现。