在项目中经常会遇到需要主动取消接口的场景,axios提供CancelToken的功能可以主动停止当前请求,从而避免无效请求,优化网络性能
场景: 远程搜索接口频繁请求,第二个接口先成功导致显示第一个接口返回的数据
/**
* 重复请求取消上次请求
*/
import axios from 'axios'
// 存储pengding请求容器
export const pendingList = new Map()
// 生成各个请求标识
export const getFetchKey = (config) => {
const { url, data, method } = config
let token
if (method === 'get') {
token = [method, url].join('&')
} else {
token = [method, url, JSON.stringify(data)].join('&')
}
return token
}
// 添加pengding请求
export const addPending = (config) => {
const fetchKey = getFetchKey(config)
if (fetchKey) {
config.cancelToken = config.cancelToken || new axios.CancelToken((cancel) => {
if (!pendingList.has(fetchKey)) {
pendingList.set(fetchKey, cancel)
}
})
}
}
// 移除pengding请求
export const removePending = (config) => {
const fetchKey = getFetchKey(config)
if (fetchKey) {
if (pendingList.has(fetchKey)) {
pendingList.delete(fetchKey)
}
}
}
// 取消请求
export const cancelPending = (config) => {
const fetchKey = getFetchKey(config)
if (fetchKey) {
if (pendingList.has(fetchKey)) {
const cancel = pendingList.get(fetchKey)
cancel('cancel')
pendingList.delete(fetchKey)
}
}
}
axios拦截器配置-防止频繁请求
- 请求时判断是否该请求是否重复,如果重复取消之前的请求
- 请求时把当前请求加入pending容器中
- 相应成功或失败时把当前请求从pending容器中移除
/**
* axios拦截器配置
*/
import {
addPending, removePending, cancelPending,
} from '@util/cancel-request'
import axios from 'axios'
// 请求拦截器
axios.interceptors.request.use(
request => {
// 发送请求前首先检查该请求是否已经重复,重复则进行取消并移除
cancelPending(request)
// 添加该请求到pendingList中
addPending(request)
return request
},
error => {
return Promise.error(error)
}
)
axios.interceptors.response.use(
response => {
// 请求成功去除pengding状态
removePending(response)
if (response.status === 200) {
return Promise.resolve(response)
} else {
return Promise.reject(response)
}
},
error => {
// 请求失败去除pengding状态
removePending(error.response)
return Promise.reject(error.response)
}
)