215 lines
5.1 KiB
Markdown
Executable File
215 lines
5.1 KiB
Markdown
Executable File
# 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
|