在请求发送过程中,服务器返回请求之前我们可以手动取消请求。
原生ajax
可以通过请求对象的abort()
方法来取消请求。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button>点击发送</button>
<button>点击取消</button>
<script>
// 获取元素;
const btns = document.getElementsByTagName('button');
let xhr = null
// 发送请求
btns[0].onclick =function (){
xhr = new XMLHttpRequest();
xhr.open('GET','http://127.0.0.1:8000/delay')
xhr.send()
}
// abort取消请求
btns[1].onclick = function (){
xhr.abort();
}
</script>
</body>
</html>
axios
方式:
1、AbortController:从v0.22.0开始,axios支持以 fetch API方式——AbortController
取消请求,用此方式一定要注意axios的版本,v0.22.0以下失效
2、cancelToken:此 API 从 v0.22.0 开始已被弃用,不应在新项目中使用
。不过我的axios当前版本v1.2.0,还可以使用cancelToken
如果想了解fetch和ajax的区别,可以看这篇文章:https://zhuanlan.zhihu.com/p/401232894
AbortController
接口表示一个控制器对象,允许你根据需要中止一个或多个 Web 请求。
看一下MDN上官方文档示例:
let controller;
const url = 'video.mp4';
const downloadBtn = document.querySelector('.download');
const abortBtn = document.querySelector('.abort');
downloadBtn.addEventListener('click', fetchVideo);
abortBtn.addEventListener('click', () => {
if (controller) {
controller.abort();
console.log('中止下载');
}
});
function fetchVideo() {
controller = new AbortController();
const signal = controller.signal;
fetch(url, { signal })
.then((response) => {
console.log('下载完成', response);
})
.catch((err) => {
console.error(`下载错误:${err.message}`);
});
}
在axios中使用
this.abortController = new AbortController();
const res = await http({
url: 'http://0.0.0.0:8088',
method: 'get',
signal: this.abortController.signal, // 带上参数
params: {
}
}).catch((err) => {
this.isRequesting3 = false;
console.log(err);
})
在取消方法中直接调用
this.abortController.abort();
取消多次重复请求
httpRequest.js
import axios from 'axios'
import store from '@/store'
import { message } from 'ant-design-vue'
const CancelToken = axios.CancelToken
let pedding = {}
const service = axios.create({
baseURL: '/',
timeout: 60000,
})
service.interceptors.request.use(config => {
config.headers['token'] = store.state.user.token
// 在参数中加个isCancelToken,用来判断该接口是否需要做多次请求取消上一个请求的操作
if (config.isCancelToken) {
// 第一种 AbortController
const controller = new AbortController();
config['signal'] = controller.signal
pedding[config.url + '&' + config.method] && pedding[config.url + '&' + config.method].abort()
pedding[config.url + '&' + config.method] = controller
// 第二种 CancelToken.source
const source = CancelToken.source()
config['cancelToken'] = source.token
pedding[config.url + '&' + config.method] && pedding[config.url + '&' + config.method].cancel()
pedding[config.url + '&' + config.method] = source
// 第三种 CancelToken
pedding[config.url + '&' + config.method] && pedding[config.url + '&' + config.method]()
config['cancelToken'] = new CancelToken((c) => {
pedding[config.url + '&' + config.method] = c
})
}
return config
}, error => {
return Promise.reject(error)
})
service.interceptors.response.use(response => {
// 这里删除key
pedding[response.config.url + '&' + response.config.method] && delete pedding[response.config.url + '&' + response.config.method]
if (response.data.code == 200) {
return response.data
} else {
message.error(response.data.msg)
return Promise.reject(response.data)
}
}, error => {
return Promise.reject(error)
})
export default service
以上三种方式选一个就可以。
使用
home.vue
<template>
<div>
<a-button>home</a-button>
<router-link to="/about">跳转about</router-link>
<a-input placeholder=""></a-input>
<a-checkbox></a-checkbox>
</div>
</template>
<script>
import { login } from '@/axios/api/home'
export default {
setup() {
login({timeRange: 'ONE_DAY'}).then(res => {
console.log('第一次调用-success')
}).catch((err) => {
console.log('第一次调用-err')
})
setTimeout(() => {
login({timeRange: 'ONE_DAY', num: 1}).then(res => {
console.log('第二次调用-success')
}).catch((err) => {
console.log('第二次调用-err')
})
}, 200)
}
}
</script>
<style lang="scss" scoped>
</style>
home.js
import request from '@/axios'
export const login = (data) => {
return request({
url: '/dc/pc/heatMap',
method: 'get',
params: data,
isCancelToken: true
})
}
保证多个请求按顺序返回
- 使用promise.all
- 请求接口中带个index标识符,和后端约定下返回数据中带上,拿到结果后做排序处理