1. 封装axios请求
在utils
文件夹下新建request.ts
文件,专用于封装axios,对于使用vue2+js的开发者,封装axios并不难,看代码都看得懂。这里我主要想展示一下如何防止重复请求。
2. 防止重复请求
思路:把每次请求的url存到一个数组,循环判断当前url是否已经存在,如果存在就取消当前请求,如果不存在就存进去并正常执行请求。并且正常之后要把这次请求的url从数组里删除掉。要不然之后都无法再次请求该地址。
所以我们需要定义一个数组存放请求类别
const reqList: any[] = []
再分别定义一个停止请求函数和允许请求函数
/**
* 阻止重复请求
* @param {Array} reqList - 当前请求列表
* @param {string} url - 当前请求地址
* @param {function} cancel - 请求中断函数
* @param {string} errorMessage - 请求中断是需提示的错误信息
*/
const handleStopRepeatRequest = (reqList: any[], url: any, cancel: any, errorMessage = ''):void => {
for (let i = 0; i < reqList.length; i++) {
if (reqList[i] === url) {
cancel(errorMessage)
return
}
}
reqList.push(url)
}
/**
* 允许某个请求可以继续进行
* @param {array} reqList 全部请求列表
* @param {string} url 请求地址
*/
const handleAllowRequest = (reqList: any[], url: any):void => {
for (let i = 0; i < reqList.length; i++) {
if (reqList[i] === url) {
// 删除当前请求
reqList.splice(i, 1)
break
}
}
}
3. 完整代码
import axios from 'axios'
import { Toast } from 'vant'
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_URL,
timeout: 10000,
transformResponse: res => res
})
// 正在请求中的请求列表
const reqList: any[] = []
/**
* 阻止重复请求
* @param {Array} reqList - 当前请求列表
* @param {string} url - 当前请求地址
* @param {function} cancel - 请求中断函数
* @param {string} errorMessage - 请求中断是需提示的错误信息
*/
const handleStopRepeatRequest = (reqList: any[], url: any, cancel: any, errorMessage = ''):void => {
for (let i = 0; i < reqList.length; i++) {
if (reqList[i] === url) {
cancel(errorMessage)
return
}
}
reqList.push(url)
}
/**
* 允许某个请求可以继续进行
* @param {array} reqList 全部请求列表
* @param {string} url 请求地址
*/
const handleAllowRequest = function(reqList: any[], url: any) {
for (let i = 0; i < reqList.length; i++) {
if (reqList[i] === url) {
reqList.splice(i, 1)
break
}
}
}
service.interceptors.request.use(config => {
let cancel
config.cancelToken = new axios.CancelToken(c => { cancel = c })
// 阻止重复请求
handleStopRepeatRequest(reqList, config.url, cancel, `${config.url} 正在请求中,请不要重复请求!`)
return config
}, function(error) {
return Promise.reject(error)
})
service.interceptors.response.use(res => {
// 增加延迟,相同请求不得在短时间内重复发送
setTimeout(() => {
handleAllowRequest(reqList, res.config.url)
}, 1000)
// 这里可以针对后端返回的code做一些出错处理...
return res.data
}, function(error) {
if (axios.isCancel(error)) {
console.log(error.message)
} else {
// 增加延迟,相同请求不得在短时间内重复发送
setTimeout(() => {
handleAllowRequest(reqList, error.config.url)
}, 1000)
}
// 这里可以针对http status做一些出错处理~
const { status } = error.response
if (status === 404) {
Toast.fail('抱歉,请求资源不存在!')
} else if (status === 301) {
Toast.fail('亲爱的,你还没登录哦!')
}
return Promise.reject(error)
})
export default service