Axios.CancelToken
axios对象有一个属性叫CancelToken,该属性提供了中断已经发出去的请求的方式。
执行器模式
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
const CancelTokenFunc = axios.CancelToken;
let cancel;
// 发送请求
axios
.get("https://jsonplaceholder.typicode.com/todos/1", {
cancelToken: new CancelTokenFunc(function executor(c) {
// 将 cancel 函数赋值给外部变量
cancel = c;
}),
})
.catch((error) => {
console.log(error.message);
});
// 取消请求
setTimeout(() => {
cancel("Operation canceled by the user.");
}, 1000);
</script>
令牌模式
// 创建一个 CancelToken 源
const CancelTokenFunc = axios.CancelToken;
const { token, cancel } = CancelTokenFunc.source();
// 发送请求
axios
.get("https://jsonplaceholder.typicode.com/todos/1", {
cancelToken: token,
})
.catch((error) => {
console.log(error.message);
});
// 取消请求
setTimeout(() => {
cancel("Operation canceled by the user.");
}, 1000);
AbortController
AbortController是一个Web API,用于控制和管理可中止的异步操作,例如 fetch 请求、DOM 操作。
中止请求
<!DOCTYPE html>
<html>
<head>
<title>中断请求demo</title>
</head>
<body>
<script>
// 创建一个 AbortController 信号源
const controller = new AbortController();
const { signal } = controller;
// 发送请求
fetch("https://jsonplaceholder.typicode.com/todos/1", {
signal,
}).catch((error) => {
console.log(error);
if (error.name === 'AbortError') {
console.log('Fetch 请求已被取消');
} else {
// 处理其他错误
}
});
// 取消请求
setTimeout(() => {
controller.abort("Operation canceled by the user.");
}, 1000);
</script>
</body>
</html>
终止axios请求
const controller = new AbortController();
axios.get('/foo/bar', {
signal: controller.signal
}).then(function(response) {
//...
});
// 取消当前请求
controller.abort()
AbortController和addEventListener配合使用
我们知道,取消监听器的方法removeEventListener(type, callback),这个callback必须和开启监听的callback是同一个函数引用,也就是说得把callback存下来,但有了signal就不用了
const controller = new AbortController();
function callback (e) {
document.addEventListener('mousemove', (e) => {
// 回调处理函数
// ...
},
{ signal: controller.signal});
}
document.addEventListener('mousedown', callback);
document.addEventListener('mouseup', controller.abort);
实现一个可以主动取消的 Promise
我们用 AbortController 以及 AbortSignal 可以很方便的构造出我们自定义的可以取消的 Promise 了。
/**
* 自定义的可以主动取消的 Promise
*/
function myCoolPromise ({ signal }) {
return new Promise((resolve, reject) => {
// 如果刚开始 signal 存在并且是终止的状态可以直接抛出异常
signal?.throwIfAborted();
// 异步的操作,这里使用 setTimeout 模拟
setTimeout(() => {
Math.random() > 0.5 ? resolve('ok') : reject(new Error('not good'));
}, 1000);
// 添加 abort 事件监听,一旦 signal 状态改变就将 Promise 的状态改变为 rejected
signal?.addEventListener('abort', () => reject(signal?.reason));
});
}
/**
* 使用自定义可取消的 Promise
*/
const ac = new AbortController();
const { signal } = ac;
myCoolPromise({ signal }).then((res) => console.log(res), err => console.warn(err));
setTimeout(() => {
ac.abort();
}, 100); // 可以更改时间看不同的结果