项目场景:
bug描述:在一个vue页面中,有异步数据请求的方法正在执行,此时切换到其他vue页面后,该异步请求不会停止。
之前写项目时,没有注意到vue路由切换后,还没执行完毕的异步请求并没有随着页面的切换而结束。
用户在当前访问页面中,异步请求的数据还没抓取完跳转到其他页面时,这个异步请求并不会终止,这对web性能和用户体验有着不小的影响。
解决思路
方法:利用axios的cancelToken取消还没执行完毕的异步请求,由路由守卫做处理,使用vuex将要取消的请求放入全局进行状态管理。
简单介绍cancelToken:
针对单个请求A发多次的情形(A1,A2…An), An都会带上cancelToken(标记),A(n+1)发起时会将An请求直接canceled(不再处理An请求响应)。
- 发起一次请求A1,且该请求中携带标识此次请求的id
- 发起一次请求A2(An表示针对同一个接口A的第n次请求),A2请求时取消原请求A1,请求A1被标识为canceled(network process工作结束)
- axios标记A1为请求异常,进入响应处理阶段(响应获取一个错误对象),请求A1结束。
- cancelToken就是一个promise,这个promise的状态的改变由使用者自己决定(执行cancel函数)。同时,这个promise的then回调就会执行,取消request。
代码部分
1. 在store中管理取消的请求操作
// store.js
const store = new Vuex.Store({
...
// store中对请求进行状态管理
// 管理取消的请求操作
state: {
axiosArr: [] // 储存cancel token
},
mutations: {
setAxiosArr (state, cancelAjax) {
state.axiosArr.push(cancelAjax.cancelToken)
},
clearAxiosArr (state) {
let message = '路由切换中断异步请求'
state.axiosArr.forEach(item => {
item()
})
state.axiosArr = []
},
},
})
export default store
2. axios封装
对request做一个条件判:在发送请求设置cancel token(就是做个标记);
再对response做一个条件判断:表达当请求失败时出现何种提示,不然会在控制台给出报错(虽然没什么影响)。
axios.interceptors.request.use(
// 对axios进行封装,设置 request 处理操作
config => {
config.cancelToken = new axios.CancelToken(cancel => { // 在发送请求设置cancel token
store.commit('setAxiosArr', { cancelToken: cancel })
})
return config
}, error => {
// Do something with request error
return Promise.reject(error)
}
)
axios.interceptors.response.use(
response => {
if (service.isCancel(error)) {
// 对axios进行封装,设置 request 和 response 的处理操作
return new Promise(() => {})
} else {
return Promise.reject(error)
}
}
)
3. 设置路由守卫对路由进行监听
// 增加路由守卫对路由进行监听,在路由切换时对上一个路由的请求进行中断
router.beforeEach((to, from, next) => {
store.commit('clearAxiosArr') // 取消请求
// console.log('路由切换')
next()
})
总结
最终实现效果:
可以看到切换vue页面后,正在执行的异步请求被中断了,从而保证了页面加载的性能和用户体验。
版权声明:本文为qq_43093129原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。