对于表单提交等场景,用户手滑可能会出现连续点击多次提交按钮的情况,此时前端需要做下请求防抖。
实现思路:定义一个防抖列表,在请求拦截中进行判断,如果这个接口中有携带我们定义需要处理防抖的参数,则进行防抖逻辑。如果只是单纯的切换查询条件,没必要也不能做防抖处理,否则会影响用户体验。
防抖逻辑大致为:
- 根据请求时已有的参数,如接口地址、请求类型、接口参数等等,自行将其拼成字符串
- 然后判断这个字符串在不在这个防抖列表中
- 如果在那就请求拦截,如果不在,则将这个字符串添加至这个防抖列表中
- 同时设置一个定时器,500毫秒后删除这个字符串
这里以vue3+axios为例
import axios, { AxiosInstance, AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios'
const config = {
baseURL: '/api',
timeout: 5000
}
const store = useGlobalToken()
class RequestHttp {
service: AxiosInstance
debouncUrlList: string[]
public constructor(config: AxiosRequestConfig) {
...
this.debouncUrlList = [] // 防抖的url列表
// 请求拦截
this.service.interceptors.request.use(
async (config: AxiosRequestConfig | any) => {
// 防抖处理
if (config.restrict) this.debounce(config)
...
)
// 响应拦截
this.service.interceptors.response.use()
}
// 防抖处理
debounce(config: AxiosRequestConfig) {
const data = config.method === 'get' ? config.params : config.data
const str = (((config.method as string) + config.url) as string) + JSON.stringify(data)
if (~this.debouncUrlList.indexOf(str)) {
ElMessage.warning('请勿重复请求')
throw new Error('重复请求')
}
this.debouncUrlList.push(str)
setTimeout(() => {
this.debouncUrlList = this.debouncUrlList.filter((e) => e !== str)
}, 500)
}
// 清除防抖
clearDebounce(config: AxiosRequestConfig) {
const data = config.method === 'get' ? config.params : config.data
const str = (((config.method as string) + config.url) as string) + JSON.stringify(data)
this.debouncUrlList = this.debouncUrlList.filter((e) => e !== str)
}
}
export default new RequestHttp(config)
clearDebounce方法为手动清除防抖,在特定的场景下自行调用即可
使用:
在定义api的文件中,在需要防抖的接口上添加restrict: true参数即可
// 新增
export const postMarketTrack = (params: any) => {
return http.post('xxx', params, { restrict: true })
}