参考:https://www.cnblogs.com/zlfProgrammer/p/11058413.html。
参考:https://blog.csdn.net/harsima/article/details/93717217。
我们经常会遇到当前页面未加载完毕时跳转路由或者返回操作, 但是通过network会发现, 若网络环境较差的情况下, 会一直pending, 切换路由后在network中添加新的请求但是正在pending的请求依然存在. 当我们在项目中做了一个上拉加载分页的时候会一直加载中, 用户等待不耐烦后可能会主动触发返回操作, 但是此刻即使用户触发返回操作, 加载分页的请求还是存在, 页面还是会一直提示加载中, 直到该请求加载成功或超时才肯罢休。最终给用户造成一些不必要的结果,同时也对web性能造成一定的影响。那么如何解决这个问题呢,方法就是监听路由,在路由切换前将上个页面的请求取消。
第一步:axios请求头设置。
import axios from 'axios'
import { store } from './store' // 引入vuex
var CancelToken = axiosss.CancelToken;
const source = CancelToken.source()
let reqList = []
const stopRepeatRequest = function (reqList, url, cancel, errorMessage) {
const errorMsg = errorMessage || ''
for (let i = 0; i < reqList.length; i++) {
if (reqList[i] === url) {
cancel(errorMsg)
return
}
}
reqList.push(url)
}
const allowRequest = function (reqList, url) {
for (let i = 0; i < reqList.length; i++) {
if (reqList[i] === url) {
reqList.splice(i, 1)
break
}
}
}
axios.interceptors.request.use(//请求拦截
config => {
if (window.localStorage.getItem("token")) {
config.headers.common["Authorization"] = window.localStorage.getItem(
"token"
);
}
config.cancelToken = new axios.CancelToken(function (cancel) {
store.commit('pushToken', {cancelToken: cancel})
})
stopRepeatRequest(reqList, config.url, source.cancel, `${config.url} 请求被中断`)
return config
}
axios.interceptors.response.use(//响应拦截
response => {
setTimeout(() => {
allowRequest(reqList, response.config.url)
}, 1000)
return response;
},
error => {
if (axiosss.isCancel(error)) {
console.log('取消了请求', error.message);
}else if (error.response) {
switch (error.response.data.status) {
case -1:
window.localStorage.removeItem("token");
router.replace({
path: "/",
query: { redirect: router.currentRoute.fullPath } //登录成功后跳入浏览的当前页面
});
}
setTimeout(() => {
allowRequest(reqList, error.config.url)
}, 1000)
return Promise.reject(error.response.data);
}
error.ace = error.message
return Promise.reject(error);
}
);
第二步:利用vuex,新建一个store.js,将取消方法cancel
放到数组中,然后在路由守卫中把数组中存有的cancel
方法都执行。
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export const store = new Vuex.Store({
state: {
cancelTokenArr: [] // 取消请求token数组
},
mutations: {
pushToken (state, payload) {
state.cancelTokenArr.push(payload.cancelToken)
},
clearToken ({ cancelTokenArr }) {
cancelTokenArr.forEach(item => {
item('路由跳转取消请求')
})
cancelTokenArr = []
}
}
})
第三步:监听路由。
router.beforeEach(function (to, from, next) {
store.commit('clearToken') // 取消请求
next()
})