devStandard/docs/learning/5-vue/3.1-axios取消请求.md
2025-03-29 14:35:49 +08:00

215 lines
5.1 KiB
Markdown
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Axios取消请求
## 原生js的abort()取消ajax请求
```jsx
<div class="page" id="app">
<button class="get-msg">获取数据</button>
<button class="cancel">取消获取</button>
</div>
<script>
var currentAjax = null
$('.get-msg').click(function () {
currentAjax = $.ajax({
type: 'GET',
url: 'http://jsonplaceholder.typicode.com/comments',
success: function (res) {
console.log(res)
},
error: function (err) {
console.log("获取失败")
}
})
})
$('.cancel').click(function () {
if (currentAjax) {
currentAjax.abort()
}
})
</script>
```
## 在axios中取消接口请求操作
Axios 提供了一个 CancelToken的函数这是一个构造函数该函数的作用就是用来取消接口请求
[官方文档: ](https://axios-http.com/zh/docs/cancellation)
方法一:
```js
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.');
```
方法二:
```js
const CancelToken = axios.CancelToken;
let cancel;
axios.get('/user/12345', {
// 在options中直接创建一个cancelToken对象
cancelToken: new CancelToken(function executor(c) {
cancel = c;
})
});
// 取消上面的请求
cancel();
```
实例:
```html
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.24.0/axios.js"></script>
</head>
<body>
<div class="page" id="app">
<button @click="getMsg" class="get-msg">获取数据</button>
<button @click="cancelGetMsg" class="cancel">取消获取</button>
<ul>
<li v-for="item in items">{{item.name}}</li>
</ul>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!',
items: [],
cancel: null
},
methods: {
getMsg () {
let CancelToken = axios.CancelToken
let self = this
axios.get('http://jsonplaceholder.typicode.com/comments',
{
cancelToken: new axios.CancelToken(function executor(c) {
self.cancel = c
// 这个参数 c 就是CancelToken构造函数里面自带的取消请求的函数这里把该函数当参数用
})
}
).then(res => {
this.items = res.data
}).catch(err => {
console.log(err)
})
},
// 开发者工具里把网速调成slow 3G
cancelGetMsg () {
this.cancel()
}
}
})
</script>
</body>
</html>
```
## 重复点击造成重复请求的问题
```tsx
// 正在进行中的请求列表
let reqList = []
/**
* 阻止重复请求
* @param {array} reqList - 请求缓存列表
* @param {string} url - 当前请求地址
* @param {function} cancel - 请求中断函数
* @param {string} errorMessage - 请求中断时需要显示的错误信息
*/
const stopRepeatRequest = function (reqList, url, cancel, errorMessage) {
const errorMsg = errorMessage || ''
for (let i = 0; i < reqList.length; i++) {
if (reqList[i] === url) {
cancel(errorMsg)
return
}
}
reqList.push(url)
}
/**
* 允许某个请求可以继续进行
* @param {array} reqList 全部请求列表
* @param {string} url 请求地址
*/
const allowRequest = function (reqList, url) {
for (let i = 0; i < reqList.length; i++) {
if (reqList[i] === url) {
reqList.splice(i, 1)
break
}
}
}
const service = axios.create()
// 请求拦截器
service.interceptors.request.use(
config => {
let cancel
// 设置cancelToken对象
config.cancelToken = new axios.CancelToken(function(c) {
cancel = c
})
// 阻止重复请求。当上个请求未完成时,相同的请求不会进行
stopRepeatRequest(reqList, config.url, cancel, `${config.url} 请求被中断`)
return config
},
err => Promise.reject(err)
)
// 响应拦截器
service.interceptors.response.use(
response => {
// 增加延迟,相同请求不得在短时间内重复发送
setTimeout(() => {
allowRequest(reqList, response.config.url)
}, 1000)
// ...请求成功后的后续操作
// successHandler(response)
},
error => {
if (axios.isCancel(thrown)) {
console.log(thrown.message);
} else {
// 增加延迟,相同请求不得在短时间内重复发送
setTimeout(() => {
allowRequest(reqList, error.config.url)
}, 1000)
}
// ...请求失败后的后续操作
// errorHandler(error)
}
)
```
[1]. https://www.jianshu.com/p/22b49e6ad819
[2]. https://blog.csdn.net/harsima/article/details/93717217