在以往的页面中,我们会遇到以下的痛点:
- 当页面的路由切换时,上一个页面的请求比较慢且没有完成,会新的页面中继续进行,如果有请求报错的话,会在新的页面中提示,通常不同的页面之前又是毫无关系的,这种提示会让用户十分困惑。
- 当用户在页面也进行搜索时候,这时如果部分请求有所延迟,会导致前面的请求在后面的请求后才回来,而用户看到的是最后一次返回的数据,这样会导致用户看到的数据,并非要搜的数据的问题。
针对以上的几种问题,对axios进行了简单的封装。支持了如下的功能
- 当发送重复请求时候,且上一条请求还未完成,可取消上一次的请求。(CANCEL_LAST_AT_MOST_ONCE)
- 当发送重复请求时候,且上一条请求还未完成,可不发送本次请求。(CANCEL_CURRENT_AT_MOST_ONCE)
- 当路由切换时,可取消上一个页面的所有请求。(cancelReqs)
以上功能的核心就是支持取消未完成的请求。可以在Axios 实例上记录所有未完成的请求。即创建一个req_pending_list,通过axios的请求拦截,当发送请求时,添加该请求到req_pending_list中,请求结束时,req_pending_list中删除该请求,具体代码如下:
dpd_axios.Axios.prototype.addPendingReq = function (
config: AxiosRequestConfig,
) {
const pending_req_key = generateKey(config);
const pending_item: reqPendingItem = {
key: pending_req_key,
method: config.method,
};
config.cancelToken = new dpd_axios.CancelToken((c) => {
pending_item.cancel = c;
});
this.req_pending_list.push(pending_item)}
针对取消重复请求,即可以在请求拦截时,判断是否是重复请求,如果是的话,cancel已有的请求,或cancel本次的请求。
dpd_axios.Axios.prototype.removeRepeatReq = function (
config: AxiosRequestConfig,
) {
const repeat_index = findRepeatReqIndex(this);
if (repeat_index > -1) {
switch (config.strategy) {
case AjaxStrategy.CANCEL_LAST_AT_MOST_ONCE:
const prev_pending_req = this.req_pending_list[repeat_index];
prev_pending_req.cancel!();
this.req_pending_list.splice(repeat_index, 1);
break;
case AjaxStrategy.CANCEL_CURRENT_AT_MOST_ONCE:
const current_pending_req = this.req_pending_list.pop();
current_pending_req!.cancel!();
break;
}
}
};
以上就是axios封装的核心代码,如果你们在业务中也遇到了和我一样的问题,可以直接使用@dpdfe/axios的库来处理,以上功能都已经支持了,使用方法和axios完全一样,欢迎下载@dpdfe/axios
通过简单的配置就可以实现取消重复请求等功能,如下所示:
instance.get('/', {strategy: AjaxStrategy.CANCEL_LAST_AT_MOST_ONCE})
快来体验吧!