一、背景
某个接口响应时间超过防抖的时间,此时重复点击,此时存在两次相同的请求,将第一次请求进行取消,保留最新请求。Github地址axios-abort
二、方案实现
axios版本大于v0.22.0
,旧版CancelToken已经废弃,本次使用 AbortController
取消请求。
测试npm包 @sunrisecn/axios-abort。
思路:根据url+method进行判断,使用map进行存储,key为url+method,value为signal数组,每次请求时判断是否是重复请求,如果是取消上次请求。
具体实现:
type TKey = {
url: string
method: string
}
class PendingStack {
private pendingMap: Map<string, AbortController[]>
constructor() {
this.pendingMap = new Map()
}
// 添加接口的 使用map存储key为url+method value:使用数组存储
public add({ url, method }: TKey): AbortSignal {
const key = `${url}-${method}`
const controller = new AbortController()
const controllerList: AbortController[] = []
if (this.pendingMap.has(key)) {
this.pendingMap.get(key)?.push(controller)
} else {
controllerList.push(controller)
this.pendingMap.set(key, controllerList)
}
return controller.signal
}
// 判断接口是否需要取消,每次有重复接口将前一条退出取消
public judge({ url, method }: TKey) {
const key = `${url}-${method}`
const controllerList = this.pendingMap.get(key)
if (Array.isArray(controllerList) && controllerList.length > 1) {
controllerList?.shift()?.abort()
}
}
// 移除接口
public remove({ url, method }: TKey) {
this.pendingMap.delete(`${url}-${method}`)
}
// 取消所有接口
public removeAll() {
this.pendingMap.forEach((controllerList) => {
controllerList.shift()?.abort()
})
this.pendingMap.clear()
}
}
export default new PendingStack()
三、项目使用
在request.js中使用
import axios from 'axios'
import abort from 'axios-abort'
const axios = axios.create(config)
axios.interceptors.request.use(
config => {
config.signal = abort.add({ url: config.url, method: config.method })
abort.judge({ url: config.url, method: config.method })
return config
},
error => Promise.reject(error)
)
axios.interceptors.response.use(
response => {
abort.remove({ url: response.config.url, method: response.config.method })
return response
},
error => Promise.reject(error)
)
API
- add
- 添加接口取消
- judge
- 判断是否满足取消条件
- remove
- 取消单个接口
- removeAll
- 取消所有接口