- 其实实现上一个请求结束前禁止下次请求的方法很多,最常见的其实就是防抖等等,但如果对所有接口都进行这个操作就很繁琐,就算写一个公共的方法也是即此。
- 既然上面的方法繁琐,那不如从根源解决问题,已知所有的接口都会通过请求拦截器/请求响应器,那么可以从此处做手脚,一次性解决所有问题。
1.最基础的请求基础代码
import axios from 'axios'
import { getItem, removeItem } from '@/utils/token'
import { Message } from 'element-ui'
import router from '@/router'
const request = axios.create({
baseURL: "/api",
})
// 请求拦截器
request.interceptors.request.use(function (config) {
config.headers.Authorization = `Bearer ${getItem("token")}`
return config;
})
// 响应拦截器
request.interceptors.response.use(function (config) {
const { status, message } = config.data
if (status == '500') {
Message.error('登录已过期,请重新登录')
removeItem('token')
router.push('/login')
} else if (status !== '200' && status !== '500') {
Message.error(message)
}
return config
}, error => {
console.log(error);
return Message.error(error)
})
export default request
2. 获取这次请求的请求信息,并做重复拦截
let requestList = []
// 请求拦截器
// 同时记录请求地址与请求方式防止拦截错误
request.interceptors.request.use(function (config) {
// headers:{
// // 不进行拦截
// serviceFiler:true
// }
// 记录当前接口信息进行拦截
if (!config.headers.serviceFiler) {
if (!requestList.some(x => x.config === `${config.url}&${config.method}`)) {
requestList.push({ config: `${config.url}&${config.method}` })
} else {
return false
}
}
config.headers.Authorization = `Bearer ${getItem("token")}`
return config;
})
3. 请求结束后清除此接口信息
// 响应拦截器
request.interceptors.response.use(function (config) {
// 移除已响应完成的接口信息 - 延迟 300 毫秒, 防止接口响应速度过快,页面还未及时更新的情况
setTimeout(() => {
requestList = requestList.filter((x, index) => x.config !== `${res.config.url}&${res.config.method}`)
}, 300);
const { status, message } = config.data
if (status == '500') {
Message.error('登录已过期,请重新登录')
removeItem('token')
router.push('/login')
} else if (status !== '200' && status !== '500') {
Message.error(message)
}
return config
}, error => {
// 如果接口是被拦截,抛出错误
if (error == `TypeError: Cannot create property 'headers' on boolean 'false'`) return Promise.reject('接口重复调用!')
return Message.error(error)
})
-
如果接口被拦截会使用
Promise.reject()
直接抛错,此时不会影响代码正常运行。
4. 完整代码
import axios from 'axios'
import { getItem, removeItem } from '@/utils/token'
import { Message } from 'element-ui'
import router from '@/router'
const request = axios.create({
baseURL: "/api",
})
let requestList = []
// 请求拦截器
// 同时记录请求地址与请求方式防止拦截错误
request.interceptors.request.use(function (config) {
// headers:{
// // 不进行拦截
// serviceFiler:true
// }
// 记录当前接口信息进行拦截
if (!config.headers.serviceFiler) {
if (!requestList.some(x => x.config === `${config.url}&${config.method}`)) {
requestList.push({ config: `${config.url}&${config.method}` })
} else {
return false
}
}
config.headers.Authorization = `Bearer ${getItem("token")}`
return config;
})
// 响应拦截器
request.interceptors.response.use(function (config) {
// 移除已响应完成的接口信息 - 延迟 500 毫秒, 防止接口响应速度过快,页面还未及时更新的情况
setTimeout(() => {
requestList = requestList.filter((x, index) => x.config !== `${res.config.url}&${res.config.method}`)
}, 500);
const { status, data, message } = config.data
if (status == '500') {
Message.error('登录已过期,请重新登录')
removeItem('token')
router.push('/login')
} else if (status !== '200' && status !== '500') {
Message.error(message)
}
return data
}, error => {
// 如果接口是被拦截,抛出错误
if (error == `TypeError: Cannot create property 'headers' on boolean 'false'`) return Promise.reject('接口重复调用!')
return Promise.reject(error);
})
export default request