由于接口响应速度等原因,在项目开发中经常需要处理重复点击导致多次调用接口的问题,针对每个接口调用单独处理相对繁琐,这里通过axios提供的拦截器实现对重复请求的统一拦截处理。
import axios from 'axios'
import md5 from 'js-md5'
let pending = {};// 网络请求记录map结构
let CancelToken = axios.CancelToken;
// 添加请求拦截器
axios.interceptors.request.use(config => {
// 通过请求url、method、params字段生成每个请求唯一的md5值
let key = md5(`${config.url}&${config.method}&${JSON.stringify(config.data)}`);
config.cancelToken = new CancelToken(c => {
if(pending[key]) {
if(Date.now() - pending[key] > 5000) {
// 同一个请求再次发起时距上次请求时间超过5s,删除对应的请求记录,重新发起请求,时间根据实际情况调整
delete pending[key];
} else {
// 5s以内的已发起请求,取消重复发送请求
c('repeated');
}
}
// 记录当前的请求,如果是进行中的请求则更新标记时间戳
pending[key] = Date.now();
});
}, error => {
return Promise.reject(error);
});
// 添加响应拦截
axios.interceptors.response.use(res => {
//response的config.url包含域名,需替换为空字符串,保证和request的url完全一致
let key = md5(`${res.config.url.replace(/.*\/api/, '')}&${res.config.method}&${res.config.data}`);
if(pending[key]) {
// 请求响应完成,删除对应的请求记录
delete pending[key];
}
return res;
}, err => {
if(err.message !== 'repeated') {
// 非取消重复请求的报错,给出错误提示
let content = '系统错误!';
if(window.navigator.onLine) {
if(/timeout/.test(err)) {
content = '请求超时!';
}
} else {
content = '网络异常!';
}
alert(content);
}
return Promise.reject(err);
})
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。