下面的方案适用于系统中的某个请求的取消,项目的请求使用
axios
封装使用场景:当页面有多个 tab,例如年、月、日的列表数据,当点击切换的时候要获取对应的数据,此时如果快速点击在tab直接反复横跳会出现下面的问题:
重复请求,切换了tab旧的页面已经看不见,没必要存留
如果使用同一套UI组件,只是数据的改变,异步的原因可能当前tab请求已经结束,然后旧的请求后结束,导致当前的页面的数据渲染出来对应不上tab
使用了
axios.CancelToken
去解决这个问题,下面讲解如何去封装
1、防抖节流
第一种能想到的简单的解决办法是使用 防抖节流去处理,发起请求的函数会被取消,但是接口是异步的,没有实质得解决问题,防抖和节流没有解决接口的调用返回顺序的问题,解决的是防止一个接口在短时间内被多次调用的问题,简单来说就是降低调用频率。
第二种能想到的简单方法就是 加锁/加loading,上一次请求未结束之前禁止用户做任何操作,显然这个也是不合理的
2、取消单个重复请求
使用 cancelToken
的语法,把当前请求的取消方法存储起来,当新的请求来到,调用取消方法取消上一次的请求
// 全局封装axios请求
import axios from "axios"
let request = axios.create({
baseURL: 'www.baudi.com',
})
request.interceptors.request.use((config) => {
// token
const { url, headers } = config
headers["Content-Type"] = "application/json";
headers.token = 'Bear Lorem ipsum dolor sit, amet consectetur adipisicing elit. Omnis libero assumenda sit cumque natus quasi reiciendis. Quam vitae qui rerum cupiditate expedita dicta deserunt? Quaerat aliquid tempora laudantium quisquam dicta?'
return config
}, error => {
return Promise.reject(new Error(error))
})
request.interceptors.response.use(
// 响应的统一处理
(res) => {
const { status } = res.data
if(status !== 200) {
return Promise.reject(new Error('请求错误'))
}
return Promise.resolve(res)
},
// 错误处理
error => {
return Promise.reject(new Error(error))
}
)
export { request }
// api文件夹下 对业务请求的封装
import { request } from "@/request";
//用户列表请求
let cancelFn = () => {}
export const getUserTypeList = () => {
cancelFn()
return request({
url: '/api/user/type/list',
cancelToken: new axios.CancelToken(c => cancelFn = c )
})
}
new axios.CancelToken()
中将取消方法c 缓存到了 cancelFn身上,每次发起请求前都调用前一次请求的取消方法,可以看到以下效果
并且,所有的请求都会带上请求配置,例如在请求头中带上了Token
3、当前项目取消重复请求
需要在全局封装axios请求 使用 map(对象)
去缓存正在进行中的请求,并使用该请求的url作为key,如果该请求成功、错误、取消都需要从 map(对象)
删除。如果一个请求正在请求中,下一个请求进来,我们可以在 map(对象)
中发现存在值,则调用取消请求的方法。