axios 取消重复请求

在开发单页面应用中,我们在使用 axios 做请求的时候,会遇到一些很不好的体验,当我们切换路由的时候,如果上个页面的请求还没结束,那么这个请求依旧会执行完,我们能不能在不需要的时候就取消掉你?

那么刚刚好, axios 可以实现这个需求。
有两种方法可以实现取消请求

方法一
官方示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const CancelToken = axios.CancelToken;
const source = CancelToken.source();

axios
.get('/user/12345', {
cancelToken: source.token,
})
.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.');

方法二
官方示例

1
2
3
4
5
6
7
8
9
10
11
12
const CancelToken = axios.CancelToken;
let cancel;

axios.get('/user/12345', {
cancelToken: new CancelToken(function executor(c) {
// executor 函数接收一个 cancel 函数作为参数
cancel = c;
}),
});

// cancel the request
cancel();

我们这里使用第二种方式

我们定义三个方法:

addPending

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const pending = new Map();

/**
* @description 添加请求
*
* @param {Object} config
*/
function addPending(config) {
// 唯一标识
let flag = config.flag || false;
if (flag) {
config.cancelToken = new axios.CancelToken(cancel => {
if (!pending.has(flag)) {
pending.set(flag, cancel);
} else {
const oldCancel = pending.get(flag);
oldCancel();
pending.set(flag, cancel);
}
});
}
return config;
}

removePending

1
2
3
4
5
6
7
8
9
10
11
/**
* @description 移除请求
*
* @param {Object} config
*/
function removePending(config) {
let flag = config.flag || false;
if (flag && pending.has(flag)) {
pending.delete(flag);
}
}

clearPending 用于在路由跳转时,清空所有请求

1
2
3
4
5
6
7
8
9
10
/**
* @description 清空所有请求
*
*/
function clearPending() {
for (const [flag, oldCancel] of pending) {
oldCancel();
}
pending.clear();
}

我们在请求体中,添加 flag 属性,来识别每一个唯一的 API

1
2
3
4
5
6
7
8
export function text(data) {
return axios({
flag: 'text',
url: 'https://easydoc.xyz/mock/NX1XF1Cx/p/29538143/0I92pgNB',
method: 'GET',
data,
});
}

这样我们的函数就写好了,只要在请求拦截中只用就可以实现了

1
2
3
4
5
6
7
8
9
10
11
12
// 请求拦截
request.interceptors.request.use(
function (config) {
// ...
return addPending(config);
},
function (error) {
// 请求错误时的处理
// ...
return Promise.reject(error);
}
);
1
2
3
4
5
6
7
8
9
10
11
12
13
// 响应拦截
request.interceptors.response.use(
function (response) {
// 请求成功,移除
removePending(response.config);
// ...
return response.data;
},
function (error) {
// ...
return Promise.reject(error);
}
);
-------------本文结束感谢您的阅读-------------
坚持原创技术分享,您的支持将鼓励我继续创作!
0%