一次操作触发多个请求,请求响应顺序错乱将会影响展示的结果
通过 Axios 的请求拦截器和响应拦截器来实现取消重复请求的功能。每当一个新的请求被发起时,都会检查是否存在相同的请求,如果存在,则取消之前的请求。使用axios.CancelToken 来创建取消令牌,并将其附加到请求配置中。当请求完成或被取消时,会从 pendingRequests 中移除对应的请求和取消函数。实际情况中并不是所有接口都需要进行取消操作,所以在请求配置中添加了一个 allowCancel标记,在请求拦截器中,如果检测到该标记存在,则进行取消操作 ,对于其他未标记允许取消请求的接口,直接发送请求,不进行取消操作。
axios 封装
import axios from 'axios';
const http = axios.create({
timeout: 20000,
withCredentials: true,
headers: { 'X-Requested-With': 'XMLHttpRequest' },
})
// 用于存储每个请求的取消函数
const pendingRequests = new Map();
// 添加请求拦截器
http.interceptors.request.use(config => {
// 如果请求配置中没有标记允许取消请求,则直接发送请求,不进行取消操作
if (!config.allowCancel) {
return config;
}
// 在发送请求之前,检查是否存在相同的请求
const requestId = JSON.stringify(config);
if (pendingRequests.has(requestId)) {
// 如果存在相同的请求,则取消之前的请求
pendingRequests.get(requestId).cancel();
}
// 创建新的取消令牌
const cancelTokenSource = axios.CancelToken.source();
config.cancelToken = cancelTokenSource.token;
// 存储新的请求和取消函数
pendingRequests.set(requestId, cancelTokenSource);
return config;
}, error => {
return Promise.reject(error);
});
// 添加响应拦截器
http.interceptors.response.use(response => {
// 请求完成后,从 pendingRequests 中移除对应的请求和取消函数
const requestId = JSON.stringify(response.config);
pendingRequests.delete(requestId);
return response;
}, error => {
// 如果请求被取消,则直接返回空响应
if (axios.isCancel(error)) {
// 自定义返回内容
return Promise.resolve({
data: null,
status: -1,
statusText: 'Request canceled'
});
}
return Promise.reject(error);
});
使用示例
// 示例函数,发起 GET 请求
const fetchData = async () => {
try {
// 允许取消请求的接口
const response1 = await api.get('/getData1', { allowCancel: true });
console.log(response1.data);
// 不允许取消请求的接口
const response2 = await api.get('/getData2');
console.log(response2.data);
} catch (error) {
console.error('Error:', error);
}
}
// 调用示例函数
fetchData();