问题
在我们日常开发中,会有重复发送同一个网络请求多次的情况,那么如何在不修改业务逻辑的前提下去优化,减少无用的网络请求呢?
解决方案
思路分析:
1.当第一次网络请求发出时,我们需要让其正常请求
2.在第一次网络请求还没有返回数据时,这个时候如果后续有重复请求发出,那么我们将其拦截掉不发送
3.将不发送的请求注册一个事件,当第一次的请求返回数据时,触发回调事件,也就是后续的重复请求将都使用第一次返回的数据
4.重复请求的定义:
请求链接相同并且请求参数相同
技术方案:
1.可以利用重写axios原型方法request来进行请求的拦截
2.可以利用事件总线eventBus进行后续重复请求的事件注册
3.等待第一次请求回来后,将后续注册的回调事件触发,返回数据
代码实现:
export function createHandleNoRepeat() {
const urlObj = {
value: {},
};
const eventBus = {
cbArr: [],
send(tag, responseData) {
this.cbArr.forEach((item) => {
if (item.tag === tag) {
item.cb(responseData);
}
});
},
on(tag, cb) {
this.cbArr.push({
tag,
cb,
});
},
remove(tag) {
this.cbArr = this.cbArr.filter((item) => {
return item.tag !== tag;
});
},
};
function requestFromCache(tag) {
return new Promise((resolve, reject) => {
try {
eventBus.on(tag, (responseData) => {
resolve(responseData);
});
} catch (error) {
reject(error);
}
});
}
const oldFun = axios.Axios.prototype.request;
axios.Axios.prototype.request = function (...args) {
const { url, data } = args[0];
const tag = `${url}|${JSON.stringify(data)}`;
if (urlObj.value[tag]) {
return requestFromCache(tag);
}
urlObj.value = { ...urlObj.value, [tag]: true };
return Reflect.apply(oldFun, this, args);
};
return {
urlObj,
handleResponse: function (resp, handleCb) {
const tempResp = handleCb(resp);
if (resp.config) {
const { url, data } = resp.config;
const tag = `${url}|${data}`;
if (tempResp) {
eventBus.send(tag, tempResp);
} else {
eventBus.send(tag, resp.data);
}
eventBus.remove(tag);
delete urlObj.value[tag];
}
if (tempResp) {
return tempResp;
} else {
return resp;
}
},
};
}