cancelToken的用法
request.js
这里的逻辑是某个特定的请求多次发起请求,只保留第一个请求,其他重复的请求取消。
import { API_MANAGE } from '@/config/global'
import store from '@/store'
import axios from 'axios'
import { Loading } from 'element-ui'
let loadingInstance
const requestMap = []
/**
* @description 添加重复的token请求
*/
function addRequest (config, requestId) {
config.cancelToken = config.cancelToken || new axios.CancelToken((cancel) => {
requestMap.push({ id: requestId, time: new Date().getTime(), fn: cancel })
})
}
/**
* @description 移除请求
*/
function removeRequest (config, requestId) {
// 只保留第一次请求,后续重复请求均取消
if (requestMap.length > 1) {
const removeRequest = requestMap.splice(1, requestMap.length - 1)
removeRequest.forEach(item => {
item.fn()
})
}
}
// 储存loading实例
const reqInstance= axios.create({
timeout: 60000,
headers: {
'Content-Type': 'application/json;charset=UTF-8'
}
})
reqInstance.interceptors.request.use(res => {
// 防止重刷token的接口多次请求
if (res.url.includes('/xxxApi')) {
const requestId = Math.random().toString(36).substring(2)
addRequest(res, requestId)
removeRequest(res, requestId)
return res
} else {
return res
}
})
reqInstance.interceptors.response.use(res => {
requestMap.splice(0, requestMap.length)
if (loadingInstance) loadingInstance.close()
if (res.status === 200) {
const {
content = null
} = res.data
const errorCode = res.data.code || res.data.errorCode
const msg = res.data.message || res.data.msg
switch (errorCode) {
case 0:
return Promise.resolve(content)
case 401: {
const errTip = {
msg,
errorCode
}
return Promise.reject(errTip)
}
default: {
const errTip = {
msg,
errorCode
}
// console.log('errTip>>>', errTip)
return Promise.reject(errTip)
}
}
}
}, error => {
requestMap.splice(0, requestMap.length)
// 取消请求还是要抛出resolve
if (axios.isCancel(error)) {
return Promise.resolve(error)
}
//关闭loading的样式
if (loadingInstance) loadingInstance.close()
const errTips = {
msg: '',
code: ''
}
if (error.response) {
const { response } = error
errTips.msg = response.data.error || response.data.msg || response.statusText || '出错了!'
errTips.code = response.data.status || response.data.errorCode || response.status || -10001
} else {
errTips.msg = error.message
errTips.code = error.code
}
return Promise.reject(errTips)
})
// 默认请求配置,默认携带token
export async function request (param) {
try {
if (requestMap.length <= 0) {
// 判断token是否即将过期
if (judgeExpiration()) {
const tokenResult = await store.dispatch('permissionManage/REFRESH_TOKEN')
// 判断token请求是否被取消,如果为否,do something
console.log('do something')
}
}
const defaultParam = {
method: 'post'
}
param = { ...defaultParam, ...param }
const config = {
baseURL: `${location.origin}/demoRequest`, //配置baseurl
headers: {
Authorization: API_MANAGE.getToken(),//配置token
...param.headers
}
}
if (param.showLoading) {
loadingInstance = Loading.service({
text: '加载中...'
})
}
let requestParam = {
...param,
...config
}
// 根据请求方式,对数据进行处理
if (param.method.toLowerCase() === 'post') {
requestParam = {
...requestParam,
data: param?.headers?.['Content-Type'] === 'multipart/form-data'
? param.data
: JSON.stringify({
...param.data
})
}
} else if (param.method.toLowerCase() === 'get') {
requestParam = {
...requestParam,
params:
{
...param.data
}
}
}
return reqInstance.request(requestParam)
} catch (e) {
if (loadingInstance) loadingInstance.close()
}
}
// 判断token即将过期(1分钟前)
function judgeExpiration () {
const expiration = API_MANAGE.getExpirationTime()
const curTime = Date.parse(new Date())
return expiration <= curTime + 60000
}
取消请求的另一种方法
发现一个比较好用axios中文文档:axios中文文档