原生Ajax
对于原生XHR对象来说,取消的ajax的关键是调用XHR对象的.abort()方法
var xhr = new XMLHttpRequest();
xhr.open("GET","https://api.github.com/");
xhr.send();
xhr.onreadystatechange=function(){
if(xhr.readyState==4&&xhr.status==200){
console.log(xhr.response);
}else{
console.log(xhr.status);
}
}
xhr.abort();
Jquery
var jq = $.ajax({
type:"get",
url:"https://api.github.com/",
dataType:"json",
success:function(data){
console.log(data);
},
error:function(err){
console.log(err);
}
})
jq.abort();
axios
普通模式
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 CancelToken(function executor(c) {
self.cancel = c
console.log(c)
// 这个参数 c 就是CancelToken构造函数里面自带的取消请求的函数,这里把该函数当参数用
})
}).then(res => {
this.items = res.data
}).catch(err => {
console.log(err)
})
//手速够快就不用写这个定时器了,点击取消获取就可以看到效果了
setTimeout(function () {
//只要我们去调用了这个cancel()方法,没有完成请求的接口便会停止请求
self.cancel()
}, 100)
},
//cancelGetMsg 方法跟上面的setTimeout函数是一样的效果,因为手速不够快,哦不,是因为网速太快,导致我来不及点取消获取按钮,数据就获取成功了
cancelGetMsg () {
// 在这里去判断你的id 1 2 3,你默认是展示的tab1,点击的时候不管你上一个请求有没有执行完都去调用这个cancel(),
this.cancel()
}
}
全局模式
有时候我们常常在发起一个请求时,希望取消前面的一个或多个请求,就要使用axios的一个方法CancelToken(), 配置方法如下。
在拦截器全局设置,用来取消所有请求:
import axios from "axios";
window.axiosCancel = [] // 全局定义一个存放取消请求的标识
const Axios = axios.create({
baseURL:"",
timeout: 10000,
...
});
//请求前拦截
Axios.interceptors.request.use(config => {
return config
// 添加取消标记
config.cancelToken = new axios.CancelToken(cancel => {
window.axiosCancel.push({
cancel
})
},function(error) {
return Promise.reject(error)
});
//请求后返回数据拦截
Axios.interceptors.response.use(res => {
},function axiosRetryInterceptor(res) {
return Promise.reject(res )
});
export default Axios
然后在组件中使用,发送一个新的请求之前,取消前面的所有正在请求的请求,如下:
methods:{
cancel(){ // 设置一个函数,在执行请求前先执行这个函数
// 获取缓存的 请求取消标识 数组,取消所有关联的请求
let cancelArr = window.axiosCancel;
cancelArr.forEach((ele, index) => {
ele.cancel("取消了请求") // 在失败函数中返回这里自定义的错误信息
delete window.axiosCancel[index]
})
},
getList(){
this.cancel() // 取消所有正在发送请求的请求
axios.post(..) // 发送一个新的请求
}
}
取消函数挂载到vue实例的原型
如果不希望每个组件里面都定义一个cancel函数,我们可以把这个函数挂载到vue实例的原型上,这样就可以在任何组件中使用cancel函数了:this.cancel(),如下main.js文件中:
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'//引入store
Vue.config.productionTip = false
// 将cancel,挂载到vue原型上
Vue.prototype.cancel = function(){
// 获取缓存的 请求取消标识 数组,取消所有关联的请求
let cancelArr = window.axiosCancel;
cancelArr.forEach((ele, index) => {
ele.cancel("取消了请求") // 在失败函数中返回这里自定义的错误信息
delete window.axiosCancel[index]
})
}
window.vm=new Vue({
el: '#app',
data(){
return{
}
},
router,
store,
components: { App },
})
每次路由页面跳转时
另外如果想每次路由页面跳转时,取消上一个页面的所有请求,我们可以把cancel()函数的内容放在路由拦截器中,router/index.js文件配置,如下:
// 引入路由以及vue,下面的是固定写法,照写就可以
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
//创建路由实例
const router = new Router({
linkActiveClass: 'app-active', // 路由点击选中时的颜色(app-active为自定义的class样式类)
routes: [
{ // 根路径
path: '/',
redirect: '/home',
component: () => import('@/pages/home') // 路由懒加载写法
},
{
path: '/home',
name: 'home',
component: () => import('@/pages/home'),
}
})
/* 路由拦截器 路由跳转前的操作 */
router.beforeEach((to, from, next) => {
// 获取缓存的 请求取消标识 数组,取消所有关联的请求
let cancelArr = window.axiosCancel;
cancelArr.forEach((ele, index) => {
ele.cancel("取消了请求") // 在失败函数中返回这里自定义的错误信息
delete window.axiosCancel[index]
})
next()
})
/* 路由拦截器 路由跳转后的操作 */
router.afterEach(to => {
})
// 将路由导出,供外部接收,主要用于main.js接收
export default router
fetch
版权声明:本文为CSDN博主「疯狂的技术宅」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/eyeofangel/article/details/105531962
以下是取消 fetch 调用的工作流程:
- 创建一个 AbortController 实例 ;
- 该实例具有 signal 属性 ;
- 将 signal 传递给 fetch option 的 signal ;
- 调用 AbortController 的 abort 属性来取消所有使用该信号的 fetch。
以下是取消 Fetch 请求的基本步骤:
const controller = new AbortController();
const { signal } = controller;
fetch("http://localhost:8000", { signal }).then(response => {
console.log(`Request 1 is complete!`);
}).catch(e => {
console.warn(`Fetch 1 error: ${e.message}`);
});
// Abort request
controller.abort();
在 abort 调用时发生 AbortError,因此你可以通过比较错误名称来侦听 catch 中的中止操作。
}).catch(e => {
if(e.name === "AbortError") {
// We know it's been canceled!
}
});
将相同的信号传递给多个 fetch 调用将会取消该信号的所有请求:
const controller = new AbortController();
const { signal } = controller;
fetch("http://localhost:8000", { signal }).then(response => {
console.log(`Request 1 is complete!`);
}).catch(e => {
console.warn(`Fetch 1 error: ${e.message}`);
});
fetch("http://localhost:8000", { signal }).then(response => {
console.log(`Request 2 is complete!`);
}).catch(e => {
console.warn(`Fetch 2 error: ${e.message}`);
});
// Wait 2 seconds to abort both requests
setTimeout(() => controller.abort(), 2000);
杰克·阿奇博尔德(Jack Archibald)在他的文章 Abortable fetch 中,详细介绍了一个很好的应用,它能够用于创建可中止的 Fetch,而无需所有样板:
function abortableFetch(request, opts) {
const controller = new AbortController();
const signal = controller.signal;
return {
abort: () => controller.abort(),
ready: fetch(request, { ...opts, signal })
};
}