问题
最近在做前端优化时,发现很多容器组件对同一个接口发起了重复调用。这是可优化的,使得在极短时间内发起的重复请求控制只请求一次,然后将结果resolve
给所有的请求即可。实现原理也很简单就是将同一个请求放入请求队列中,直到有一个请求结果返回时,将请求队列所有的内容resolve
这个结果即可。
伪代码实现如下
针对问题代码实现如下所示:
function requestOnceWrap(fn, ctx = null, wait = 0) {
const resolveQueue = [];
const rejectQueue = [];
let requestTime = '';
function request(...args) {
return new Promise(async (resolve, reject) => {
if (resolveQueue.length || (requestTime && Date.now() - requestTime <= wait)) {
resolveQueue.push(resolve);
rejectQueue.push(reject);
} else {
if (!requestTime) requestTime = Date.now();
try {
const res = await fn.apply(ctx, args);
[resolve, ...resolveQueue].forEach(resolve => resolve(response));
} catch(e) {
[reject, ...rejectQueue].forEach(reject => reject(err));
}
resolveQueue.length = 0;
rejectQueue.length = 0;
}
});
};
return request;
};
缓存
针对不常变动的数据,也可以将请求结果进行缓存,再次请求数据时可以直接使用缓存的结果。
function requestOnceWrap(fn, ctx = null, wait = 0) {
const resolveQueue = [];
const rejectQueue = [];
let requestTime = '';
// 初始化缓存
let cache = null;
function request(...args) {
return new Promise(async (resolve, reject) => {
// 已有缓存数据,直接 return 数据
if (cache) {
return resolve(cache);
}
if (resolveQueue.length || (requestTime && Date.now() - requestTime <= wait)) {
resolveQueue.push(resolve);
rejectQueue.push(reject);
} else {
if (!requestTime) requestTime = Date.now();
try {
const res = await fn.apply(ctx, args);
// 进行结果缓存
cache = res;
[resolve, ...resolveQueue].forEach(resolve => resolve(response));
} catch(e) {
[reject, ...rejectQueue].forEach(reject => reject(err));
}
resolveQueue.length = 0;
rejectQueue.length = 0;
}
});
};
return request;
};
请求重试
如上的warp
函数对于所有的请求要么就是全部resolve
,要么就是全部reject
,没有重试机制。但是对于部分网络问题造成的请求错误如:409、403、502等http code
是可以进行重试机制的,从而实现请求正常返回的,伪代码实现如下:
const MAX_RETRY_COUNT = 3;
const requestRetry = async (fn, config = {
retry: 0,
onSuccess: (res) => {},
onError: (err) => {},
}) => {
try {
const res = await fn();
config.onSuccess(res);
} catch(e) {
if (config.retry < MAX_RETRY_COUNT) {
await requestRetry(fn, {
retry: config.retry + 1,
onSuccess: (res) => {},
onError: (err) => {},
})
} else {
config.onError(e);
}
}
};
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!