1、基本流程
- 配置 cancelToken 对象
- 缓存用于取消请求的 cancel 函数
- 在后面特定时机调用 cancel 函数取消请求
- 在错误回调中判断如果 error 是 cancel, 做相应处理
2、实现功能
- 点击按钮, 取消某个正在请求中的请求
- 在请求一个接口前, 取消前面一个未完成的请求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>取消请求</title>
</head>
<body>
<button onclick="getProducts1()">获取商品列表1</button><br>
<button onclick="getProducts2()">获取商品列表2</button><br>
<button onclick="cancelReq()">取消请求</button><br>
<script src="https://cdn.bootcss.com/axios/0.19.0/axios.js"></script>
<script>
let cancel // 用于保存取消请求的函数
function getProducts1() {
axios({
url: 'http://localhost:4000/products1',
cancelToken: new axios.CancelToken((c) => { // c是用于取消当前请求的函数
// 保存取消函数, 用于之后可能需要取消当前请求
cancel = c
})
}).then(
response => {
cancel = null
console.log('请求1成功了', response.data)
},
error => {
cancel = null
console.log('请求1失败了', error.message, error)
}
)
}
function getProducts2() {
axios({
url: 'http://localhost:4000/products2'
}).then(
response => {
console.log('请求2成功了', response.data)
},
error => {
cancel = null
console.log('请求2失败了', error.message)
}
)
}
function cancelReq() {
// alert('取消请求')
// 执行取消请求的函数
if (typeof cancel === 'function') {
cancel('强制取消请求')
} else {
console.log('没有可取消的请求')
}
}
</script>
</body>
</html>
在请求一个接口前, 取消前面一个未完成的请求:
function getProducts1() {
// 在准备发请求前, 取消未完成的请求
if (typeof cancel==='function') {
cancel('取消请求')
}
axios({
url: 'http://localhost:4000/products1',
cancelToken: new axios.CancelToken((c) => { // c是用于取消当前请求的函数
// 保存取消函数, 用于之后可能需要取消当前请求
cancel = c
})
}).then(
response => {
cancel = null
console.log('请求1成功了', response.data)
},
error => {
if (axios.isCancel(error)) {
// cancel = null
// 若不用这个,如果点三次第一个函数,会导致后面的第2个不能被取消,
// 因为第一个函数的error回调函数把cancel=null,此时正在执行第二个函数,
// 最后导致点击第三个函数时,判断的cancel=null,使得不能取消掉之前第二个函数
console.log('请求1取消的错误', error.message)
} else { // 请求出错了
cancel = null
console.log('请求1失败了', error.message)
}
}
)
}
使用拦截器优化代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>取消请求</title>
</head>
<body>
<button onclick="getProducts1()">获取商品列表1</button><br>
<button onclick="getProducts2()">获取商品列表2</button><br>
<button onclick="cancelReq()">取消请求</button><br>
<script src="https://cdn.bootcss.com/axios/0.19.0/axios.js"></script>
<script>
// 添加请求拦截器
axios.interceptors.request.use((config) => {
// 在准备发请求前, 取消未完成的请求
if (typeof cancel==='function') {
cancel('取消请求')
}
// 添加一个cancelToken的配置
config.cancelToken = new axios.CancelToken((c) => { // c是用于取消当前请求的函数
// 保存取消函数, 用于之后可能需要取消当前请求
cancel = c
})
return config
})
// 添加响应拦截器
axios.interceptors.response.use(
response => {
cancel = null
return response
},
error => {
if (axios.isCancel(error)) {// 取消请求的错误
// cancel = null
console.log('请求取消的错误', error.message) // 做相应处理
// 中断promise链接
return new Promise(() => {})
} else { // 请求出错了
cancel = null
// 将错误向下传递
// throw error
return Promise.reject(error)
}
}
)
let cancel // 用于保存取消请求的函数
function getProducts1() {
axios({
url: 'http://localhost:4000/products1',
}).then(
response => {
console.log('请求1成功了', response.data)
},
error => {// 只用处理请求失败的情况, 取消请求的错误的不用
console.log('请求1失败了', error.message)
}
)
}
function getProducts2() {
axios({
url: 'http://localhost:4000/products2',
}).then(
response => {
console.log('请求2成功了', response.data)
},
error => {
console.log('请求2失败了', error.message)
}
)
}
function cancelReq() {
// alert('取消请求')
// 执行取消请求的函数
if (typeof cancel === 'function') {
cancel('强制取消请求')
} else {
console.log('没有可取消的请求')
}
}
</script>
</body>
</html>