axios 拦截器与取消 pending 状态请求
axios 拦截器与取消 pending 状态请求/*** axios 拦截器配置*/import axios from 'axios'import { Notification } from 'element-ui'import router from '../router/index.js'// 跳转到登录页面const gotoLoginPage = function...
·
axios 拦截器与取消 pending 状态请求
/**
* axios 拦截器配置
*/
import axios from 'axios'
import { Notification } from 'element-ui'
import router from '../router/index.js'
// 跳转到登录页面
const gotoLoginPage = function () {
// 使用 setTimeout 是为了让 Notification 提示显示出来再跳转
setTimeout(() => {
router.replace(`/login?redirect=${encodeURIComponent(location.pathname + location.search)}`)
}, 1000)
}
axios.defaults.timeout = 5000 // 默认的超时时间
axios.defaults.withCredentials = true // 表示跨域请求时是否需要使用凭证
/**
* 正在进行(pending 状态)的请求记录
*/
// 记录所有正在进行(pending 状态)的请求的 "唯一值" 和 "取消请求方法"
const allPendingRequestsRecord = []
/**
* 通过请求的 url 和 method 来标示请求唯一值
* @param {*} config 配置信息
* @returns
*/
function getUniqueId (config) {
return `url=${config.url}&method=${config.method}`
}
/**
* 取消请求,并移除记录
* @param {*} config 配置信息
*/
function removePendingRequestRecord (config) {
allPendingRequestsRecord.some((item, index) => {
if (item.id === getUniqueId(config)) {
// console.log('-- cancel id:', item.id)
item.cancel() // 取消请求
allPendingRequestsRecord.splice(index, 1) // 移除记录
return true
}
})
// console.log('-- allPendingRequestsRecord:', allPendingRequestsRecord.length, JSON.stringify(allPendingRequestsRecord))
}
/**
* 取消所有请求并移除所有记录
*
* 页面切换时,取消所有请求并移除所有记录 useAge:
* import {removeAllPendingRequestsRecord} from './helper/axios';
* router.beforeEach((to, from, next) => {
* removeAllPendingRequestsRecord();
* }
*/
export function removeAllPendingRequestsRecord () {
allPendingRequestsRecord.forEach((item) => {
item.cancel('page changes') // 取消请求
})
allPendingRequestsRecord.splice(0) // 移除所有记录
}
// 添加请求拦截器
axios.interceptors.request.use(
config => {
// 在发送请求之前做些什么
// 在 get 请求上带上时间戳
if (config.method === 'get') {
config.url = config.url + '?' + new Date().getTime()
}
// 通过添加随机 uniqueCancel 值,确保每个请求具有唯一标示
config.url = `${config.url}?uniqueCancel_${Math.random().toString(36).substr(2)}`
// 在请求发送前执行一下取消操作,防止重复发送请求(dashboard 类似页面具有重复多次的相同请求,所有不能在全局做防止重复)
// removePendingRequestRecord(config)
// 设置请求的 cancelToken
config.cancelToken = new axios.CancelToken(function executor (cancel) {
// 添加记录,记录请求的唯一值和取消方法
allPendingRequestsRecord.push({ id: getUniqueId(config), cancel })
})
// console.log('-- request config:', config)
return config
},
error => {
// 对请求错误做些什么
Promise.reject(error)
}
)
// 添加响应拦截器
axios.interceptors.response.use(
res => {
// 对响应数据做点什么
// 307 表示 session 过期,需要重新登录
if (res.status === 200 && res.data.code === 307) {
removeAllPendingRequestsRecord()
Notification.info({
title: '消息',
message: '登录失效,请重新登录'
})
// 移除菜单和权限信息
localStorage.removeItem('menus')
localStorage.removeItem('buttons')
sessionStorage.removeItem('isLoadNodes')
// window.location.href = (res.data.content && res.data.content.loginPath) || '/enmoLogin'
gotoLoginPage()
return Promise.reject(res)
}
// 请求成功后移除记录
removePendingRequestRecord(res.config)
if (!res.data) {
return Promise.reject(res)
}
return res
},
error => {
// 对响应错误做点什么
if (error && error.response) {
switch (error.response.status) {
case 400:
error.message = '错误信息:' + '请求参数错误'
break
case 401:
// 401 说明登录验证失败,需要重新验证
error.message = '未登录'
removeAllPendingRequestsRecord()
gotoLoginPage()
break
case 402:
error.message = '错误信息:您还没有该路径的访问权限'
break
case 404:
error.message = '错误信息:请求地址出错'
break
case 500:
error.message = 'message:' + error.response.data.message + ',exception:' + error.response.data.exception
break
case 502:
error.message = '错误信息:网关错误'
break
case 504:
error.message = '错误信息:网关超时'
break
default:
}
Notification({
title: '错误码:' + error.response.status,
dangerouslyUseHTMLString: true,
message: error.message,
type: 'error'
})
}
// 请求失败,移除记录
removePendingRequestRecord(error.response.config)
return Promise.reject(error)
}
)
// Plugin 包装
const axiosPlugin = {
install (Vue) {
Vue.prototype.$http = axios
Vue.prototype.$base = '/commonApi'
Vue.prototype.$mock = '/mockApi'
}
}
export default axiosPlugin
// 测试 Plugin 包装:
// this.$http.get(`${ this.$base }/dbaasDbManage/instance`, {params: {
// pageSize: 15,
// pageNum: 1,
// queryFiled: ''
// }}).then(function(res){
// console.log('-- res.data field:', res.data);
// },function(res){
// console.log('-- res.status field:', res.status);
// });
// 测试 Mock 接口:
// this.$http.get(`${this.$mock}/dbaas/getMockInfo`).then(function (res) {
// console.log('-- res.data field:', res.data)
// }, function (res) {
// console.log('-- res.status field:', res.status)
// })
更多推荐
已为社区贡献1条内容
所有评论(0)