vue路由切换时终止异步请求【转载】
项目场景:
bug描述:在一个vue页面中,有异步数据请求的方法正在执行,此时切换到其他vue页面后,该异步请求不会停止。
之前写项目时,没有注意到vue路由切换后,还没执行完毕的异步请求并没有随着页面的切换而结束。
用户在当前访问页面中,异步请求的数据还没抓取完跳转到其他页面时,这个异步请求并不会终止,这对web性能和用户体验有着不小的影响。
解决思路
方法:利用axios的cancelToken取消还没执行完毕的异步请求,由路由守卫做处理,使用vuex将要取消的请求放入全局进行状态管理。
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) { 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页面后,正在执行的异步请求被中断了,从而保证了页面加载的性能和用户体验。