背景:
其实我感觉没什么用,影响不会很大,但是还是那句话:你可以没有,但不可以不会~ 程序员还是得有所追求,严谨🧐
使用场景:
发生重复请求的场景一般有这些:
- 快速连续点击一个按钮,如果你没有做禁用处理,那么弱网情况下就可以不断点击触发请求。
- 对于列表数据,可能有tab状态栏的频繁切换查询,如果请求响应很慢,也会产生重复请求。当然现在很多列表都会做缓存,如Vue中用
<keep-alive />。
方法
ajax用.abort()中断一个已被发出的请求,我们主要讲axios,用的是CancelToken,这是文档。
思路
- 定义pending数组,收集请求信息。
- 用axios生成cancel函数和cancelToken。
- 每次axios请求之前判断pending中是否有该请求信息,如果有,则利用axios生成的cancel函数和 cancelToken取消之前请求,再把本次请求信息添加pending。如果没有,则直接添加。
- 接口返回后,移除pending数组中该请求信息。
直接上代码
// utils/request.js
import axios from 'axios'
imort { Message } from 'element-ui'
imiport router from '../router'
imort Qs from 'qs'
function myAxios(axiosConfig, customOptions) {
const service = axios.create({
// baseURL: 'XXX'
timeout: 6000, // request timeout
withCredentials: true // 允许为自己域设置cookie
})
// 自定义配置
let custom_options = Object.assign({
repeat_request_cancel: false, // 是否开启取消重启请求,默认为true
}, customOptions)
// request interceptor
service.interceptors.request.use(
config => {
config.headers.Authorization = 'Bearer ' + localStorage.token //JWT认证
custom_options.repeat_request_cancel && addPendingRequest(config) // 把当前请求信息添加到pendingRequest对象中
return config
},
err => {
// 返回带有拒绝原因的Promise对象
return Promise.reject(err)
}
)
// response interceptor
service.interceptors.response.use(
response => {
removePendingRequest(response.config) // 从pendingRequest对象中移除请求
const { data, status } = response
// do some thing
},
err => {
removePendingRequest(err.config || {}) // 从pendingRequest对象中移除请求
if (axios.isCancel(err)) {
console.log('已取消重复请求' + err.message)
}
return Promise.reject(err)
}
)
return service(axiosConfig)
}
// 用于根据当前请求的信息,生成请求Key
function generateReqKey (config) {
const { method, url, params, data } = config
return [method, url, Qs.stringify(params), Qs.stringify(data)].join('&')
}
// 用于把当前请求信息添加到pendingRequest对象中
const pendingRequest = new Map()
function addPendingRequest (config) {
const requestKey = generateReqKey(config)
config.cancelToken = config.cancelToken || new axios.CancelToken((cancel) => {
if(!pendingRequest.has(requestKey)) {
pendingRequest.set(sequestKey, cancel)
}
})
}
// 检查是否有存在重复请求,若存在则取消已发请求
function removePendingRequest (config) {
const requestKey = generateReqKey(config)
if (pendingRequest.has(requestKey)) {
const cancelToken = pendingRequest.get(requestKey)
cancelToken(requestKey)
pendingRequest.delete(requestKey)
}
}
export default myAxios
// home.vue import axios from '../utils/request'
axios({
method: 'post',
url: 'xxx',
params: {xxx}
}, {
repeat_request_cancel: false
})
.then(res => xxx)
.catch(err => xxx)
结尾
有收获希望能一键三连😁谢谢~