取消请求的必要性
在切换页面后,取消之前还未完成的axios请求,以免之前的请求结果影响当前页面的判断。
原理
实现的原理:
1、取消axios请求的方法;
2、将当前页面的请求取消方法存在state中,在router.beforeEach()钩子函数中遍历执行该取消方法。
取消axios请求的方法
其实原理都是通过axios的cancelToken属性来实现,在封装好的axios中添加以下代码:
const instance = axios.create({
// baseURL: '',
timeout: 30000 // 请求超时时间
});
let cancel = null
instance.interceptors.request.use(config => {
config.cancelToken = new axios.CancelToken(cancel => {
cancel = cancel
})
})
// 当需要取消请求时,用cancel()来取消请求
instance.interceptors.response.use(err => {
if (axios.isCancel(err)) {
console.log('Request canceled', err.message);
return
}
// 处理错误
console.error(err)
return Promise.reject(err) // 返回接口返回的错误信息
})
结合vue路由跳转实现取消请求
接下来就是利用vuex和router来实现我们的需求
首先改造一下上面的代码,其实就是在axios.cancelToken函数返回中将所有请求添加到state中去:
// http.js
const instance = axios.create({
// baseURL: '',
timeout: 30000 // 请求超时时间
});
let cancel = null
instance.interceptors.request.use(config => {
config.cancelToken = new axios.CancelToken(cancel => {
store.commit('addCancelToken', cancel)
})
})
// state/index.js
state: {
platform: '',
includeRouters: [],
cancelTokenArr: []
},
mutations: {
addCancelToken(state, cancel) {
if (!state.cancelTokenArr) {
state.cancelTokenArr = []
}
if (cancel) {
state.cancelTokenArr.push(cancel)
}
},
// 取消所有请求
clearCancelToken(state) {
state.cancelTokenArr.forEach(c => {
if (c) {
c()
}
})
state.cancelTokenArr = []
}
}
然后再router文件中增加router.beforeEach钩子函数:
router.beforeEach((to, from, next) => {
// 切换路由时先取消所有请求
store.commit('clearCancelToken')
})
OK,这样操作之后,切换路由时就会取消之前所有尚未返回结果的请求。
注意❗
注意: 在前端页面取消的请求并不会影响到后端,也就是说你已经发出去的请求后端还是会接收到,只不过前端不再接收服务器返回的结果了。
测试
我们来测试一下,这里介绍一个浏览器的设置,可以把浏览器的网速调慢,网速慢了请求响应就慢了,方便我们测试。
这里有一些默认的配置,也可以自定义网速,这里就不多介绍了,我们把网速切换为Fast 3G来测试一下。
当我快速切换两个路由时,上一个页面未完成的请求的状态为取消(canceled),证明我们成功啦。