# axios 中取消请求及阻止重复请求的
今天在掘金看到了一篇文章感觉写的非常的 nice 前端防御性编程,里面的内容写的非常的实用之前一直没弄的东西也弄弄完了。
在实际项目中,我们可能需要对请求进行“防抖”处理。这里主要是为了阻止用户在某些情况下短时间内重复点击某个按钮,导致前端向后端重复发送多次请求,还有一种情况就是举个例子:几个 Tab 的切换但是下面的内容页用的是同一个,当网络情况差的时候切换的时候会出现后一个 Tab 渲染了前一个 Tab 请求的内容。
为了防止这些发生,我们在 axios 请求的时候要做一些判断,用到的核心方法就是 axios 提供的 CancelToken
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios
.get("/user/12345", {
// 必须对请求进行cancelToken设置
cancelToken: source.token
})
.catch(function(thrown) {
// 如果请求被取消则进入该方法判断
if (axios.isCancel(thrown)) {
console.log("Request canceled", thrown.message);
} else {
// handle error
}
});
// 取消上面的请求
// source.cancel('messge') message为可选项,必须为String
source.cancel("Operation canceled by the user.");
const CancelToken = axios.CancelToken;
let cancel;
axios.get("/user/12345", {
// 在options中直接创建一个cancelToken对象
cancelToken: new CancelToken(function executor(c) {
cancel = c;
})
});
// 取消上面的请求
cancel();
上面是官方文档上的两个方法,然后我将方法修改了下能同时满足取消前面的全部请求,和取消相同请求。
// 创建一个 axios 实例
const service = axios.create({
baseURL: process.env.VUE_APP_API,
timeout: 5000 // 请求超时时间
});
// 存储的HTTP请求
let pending = [];
let cancelToekn = axios.CancelToken;
let removePending = (config, isAll) => {
for (let i = 0; i < pending.length; i++) {
if (isAll) {
pending[i].fun();
pending.splice(i, 1);
i--;
} else {
// 通过记录的url, method和参数来判断请求是否是同一个
if (pending[i].name == config.url + JSON.stringify(config.data) + "&" + config.method) {
pending[i].fun();
pending.splice(i, 1);
break;
}
}
}
};
// 请求拦截器
service.interceptors.request.use(
config => {
// 在HTTP请求前取消前面的所有请求(config.headers.removeP这个是自定义传参来确定这个请求是否需要取消前面所有的请求 通常用在渲染数据的接口)
if (config.headers.removeP) removePending(config, true);
// 在HTTP请求前取消相同的请求
else removePending(config, false);
// 记录本次HTTP请求
config.cancelToken = new cancelToekn(c => {
pending.push({
name: config.url + JSON.stringify(config.data) + "&" + config.method,
fun: c
});
});
return config;
},
error => {
// 发送失败
console.log(error);
return Promise.reject(error);
}
);
// 响应拦截器
service.interceptors.response.use(
response => {
setTimeout(() => {
// 请求成功后删除记录(延时是为了防止短时间内重复请求)
removePending(response.config);
}, 500);
},
error => {
// 判断是否是被取消请求
if (!axios.isCancel(error)) {
setTimeout(() => {
// 请求成功后删除记录(延时是为了防止短时间内重复请求)
removePending(error.config);
}, 500);
}
return Promise.reject(error);
}
);
← 2019-12-05 2019-12-12 →