request.js封装
import Vue from 'vue'
import router from '@/router'
import store from '@/store'
import axios from 'axios'
import { Message } from 'element-ui'
const popupErrorMessage = (function popupErrorMessage() {
const cacheMessage = []
return function(message) {
if (!message) {
return
}
if (cacheMessage.indexOf(message) !== -1) {
return
}
Message.error(message)
cacheMessage.push(message)
const timeoutId = setTimeout(() => {
cacheMessage.splice(cacheMessage.indexOf(message), 1)
clearTimeout(timeoutId)
}, 1000)
}
})()
Vue.prototype.$http = axios
const CancelToken = axios.CancelToken
class PendingRequest {
constructor() {
/** @type { Map<string, import('axios').Canceler> } */
this.pendingMap = new Map()
}
/**
* 发起新的请求前,清除重复请求,并生成新的请求token
* @param {string} url - 请求的url做为唯一key
* @returns {import('axios').CancelToken}}
*/
cancelToken(url) {
const { pendingMap } = this
const key = url.split('?')[0]
if (pendingMap.has(key)) {
pendingMap.get(key)('取消重复请求')
}
return new CancelToken(cancel => {
pendingMap.set(key, cancel)
})
}
cancelAllToken() {
const { pendingMap } = this
pendingMap.forEach(cancelToken => cancelToken('取消重复请求'))
pendingMap.clear()
}
/**
* 删除已完成的请求token
* @param {string} url - 请求的url做为唯一key
*/
delete(url) {
const key = url.split('?')[0]
this.pendingMap.delete(key)
}
}
const pendingRequest = new PendingRequest()
const request = axios.create({
baseURL: process.env.VUE_APP_URL,
})
request.interceptors.request.use(
config => {
if (!config.noCancelPendingRequest) {
config.cancelToken = pendingRequest.cancelToken(config.url)
}
const token = localStorage.getItem('token')
if (token) {
config.headers.token = token // 请求头部添加token
}
return config
},
error => {
return Promise.reject(error)
},
)
request.interceptors.response.use(
response => {
const { config, data } = response
pendingRequest.delete(config.url)
if (data.respCode === '0000' || data.respCode === '200') {
return Promise.resolve(data)
}
const errorMessage = getCustomErrorMessage(data.respCode || data.status)
if (errorMessage === false) {
console.error(`接口响应错误: ${config.url}\n响应内容: ${data}`)
}
if (!process.env.production) {
console.warn(
`error_code: ${data.respCode},error_message: ${data.respMsg}`,
)
}
!config.noHandleErrorMessage &&
popupErrorMessage(errorMessage || data.respMsg || data)
return Promise.reject(data)
},
error => {
const { response, config = {} } = error
if (response) {
const errorMessage = getHttpErrorMessage(response.status)
errorMessage && popupErrorMessage(errorMessage)
return Promise.reject({
message: errorMessage,
respCode: response.status,
})
} else {
if (config.noHandleErrorMessage) {
// 不处理错误消息
return Promise.reject(error)
} else if (error.message.includes('timeout')) {
// 请求超时或者网络有问题
popupErrorMessage('请求超时!请检查网络是否正常')
} else if (error.message.includes('Network Error')) {
popupErrorMessage('网络连接错误')
} else if (error.message === '取消重复请求') {
// 取消重复请求 不做处理
return Promise.reject({})
} else {
popupErrorMessage('请求失败,请检查网络是否已连接')
}
}
return Promise.reject(error)
},
)
function getHttpErrorMessage(code) {
switch (code) {
case 404:
return '网络请求不存在'
case 503:
return '服务器目维护中'
case 500:
return '服务器内部错误'
}
}
function getCustomErrorMessage(code) {
if (!code) {
return false
}
switch (code.toString()) {
case '403':
handleCustom403Error()
return '登录已失效,请重新登录'
case '1003':
return '没有记录被修改'
case '1006':
return '没有记录被删除'
}
}
function handleCustom403Error() {
pendingRequest.cancelAllToken()
store.commit('CLEAR_VIEW_TAG')
if (localStorage.getItem('token')) {
localStorage.clear()
router.push('/login')
}
}
export function cancelToken(url) {
const { pendingMap } = pendingRequest
const key = url.split('?')[0]
if (pendingMap.has(key)) {
pendingMap.get(key)('取消重复请求')
}
}
export default function(url, params = {}, config = {}) {
return request.post(url, params, config).catch(error => {
!process.env.production && console.log(error)
return Promise.reject(error)
})
}