场景
- 用户在刚进入一个页面时,可能发送很多请求拿数据,这是如果用户快速切换至另一个页面或者组件,有的请求还没完成,而实际上这些请求已经没有用处,而如果此时刚好请求发生了错误触发了全局错误处理,可能会带来较差的用户体验。所以需要我们在合适的时候中断已经发出的请求。
- 取消重复请求
本质
当一个ajax请求被发出时,XMLHttpRequest.abort()方法会终止该请求,它的readyState被置为0,status被置为0
axios中断请求
利用axios.CancelToke回调函数来中断请求。
- 创建请求池:当一个请求的method,url和params或者data全部重复时可认为是同一个请求,请求池以这个序列化后的字符串为参数,值为回调函数的cancel.
import axios from "axios"
import qs from 'qs';
import { InternalAxiosRequestConfig } from "axios"
let request = new Map()
// 添加请求
export const addRequest = (config: InternalAxiosRequestConfig): void => {
const url = [
config.method,
config.url,
qs.stringify(config.params),
qs.stringify(config.data)
].join("&")
config.cancelToken = config.cancelToken || new axios.CancelToken(cancel => {
if (!request.has(url)) { request.set(url, cancel) }
})
}
- 移除请求
// 移除请求
export const removeRequest = (config: InternalAxiosRequestConfig) => {
const url = [
config.method,
config.url,
qs.stringify(config.params),
qs.stringify(config.data)
].join("&")
if (request.has(url)) {
const cancel = request.get(url)
cancel()
request.delete(url)
}
}
- 清空请求
// 清空请求
export const clearRequest = () => {
for (const [url, cancel] of request) {
cancel()
}
request.clear()
}
- 在请求拦截器中首先移除请求,之后将本次请求添加进请求池中
import axios from "axios";
import { addRequest, removeRequest } from "@/utils/cancelRequest"
const request = axios.create({
baseURL: "XXX",
})
request.interceptors.request.use(config => {
removeRequest(config)
addRequest(config)
return config
}, error => {
console.log("request error:", error);
})
6.在响应拦截器中移除本次请求
request.interceptors.response.use(res => {
removeRequest(res.config)
return res.data
}, error => {
return Promise.reject()
})
export default request
以上可实现中断重复需求的操作
7. 在beforeEach中执行clearRequest方法可在每次路由跳转时取消掉还没完成的请求
const router = createRouter({
history: createWebHashHistory(),
routes,
})
router.beforeEach((to, from, next) => {
clearRequest()
next()
})
export default router