思路:
- 定义一个http的状态map,存储请求的pending和complete,目的是为了解决同一个请求,在同一时间发起多次请求,为了避免发起多次同一个接口,存储status,本次request尚未【success】(非error),不发起下一次同一接口
- 定义回调的map,存储请求的回调函数,目的是为了,请求成功之后,触发回调,尤其是同一时间发起多次同一个request,当一个pending时,其他均置于map回调中,当success时,以此触发每个回调
- 定义一个返回值map,存储每个request的结果,当下一次发起同一个请求时,去缓存里查找同时返回对应的结果,如果未查到,则发起请求
- 定义请求的id,以参数、url以及请求方式当id,以此判断这次请求在缓存中是否有这个id
import { singleton } from "./singleton";
class Cache {
statusMap = new Map();
cacheMap = new Map();
cbMap = new Map();
constructor() {
}
setCache(request) {
const cacheKey = this.guidGeneratorRequestKey(request);
if (this.statusMap.has(cacheKey)) {
const status = this.statusMap.get(cacheKey);
if (status === 'complete') {
return Promise.resolve(this.cacheMap.get(cacheKey));
}
if (status === 'pending') {
return new Promise((resolve, reject) => {
if (this.cbMap.has(cacheKey)) {
const arr = this.cbMap.get(cacheKey);
arr.push({
onSuccess: resolve,
onFail: reject,
})
this.cbMap.set(cacheKey, arr)
} else {
this.cbMap.set(cacheKey, [
{
onSuccess: resolve,
onFail: reject,
}
])
}
})
}
}
this.statusMap.set(cacheKey, 'pending');
return new Promise((resolve, reject) => {
xx({
url: request.url,
method: request.method || 'get',
header: {
},
data: request.params,
timeout: 10000,
success: (res) => {
console.log('[cache]: params, url, res--setCache:', request.params, request.url, res);
const token = res.data.data || '';
if (res.status == 200 || res.statusCode == 200) { // iOS: status;Android:statusCode
this.statusMap.set(cacheKey, 'complete');
this.cacheMap.set(cacheKey, token);
resolve(token);
} else {
this.statusMap.delete(cacheKey)
reject(res);
}
if (this.cbMap.has(cacheKey)) {
const arr = this.cbMap.get(cacheKey);
for (let list of arr) {
list.onSuccess && list.onSuccess(token);
}
this.cbMap.delete(cacheKey)
}
},
failure: (error) => {
console.error('[cache]: error--setCache:', error);
reject(error);
},
});
})
}
guidGeneratorRequestKey(config) {
return `url=${ config.url }&method=${ config.method }¶ms=${ JSON.stringify(config.params) }`;
}
}
export default singleton(Cache);
以上为基本demo,,此方法有几处待优化:
- 成功回调应返回data,而不是data中的某个字段(本方法为解决每次请求接口都会请求token接口而封装,故只返回了token而已)
- 上文提及到,同一时间发起多次同一接口,除第一个真正发起了http请求,其余均被推到回调cache中,问题是,如果第一次请求超时,或者报错,进而导致后续http均不会收到数据,所以该方法应该有重试功能
- 在这里没有考虑并发问题,应该考虑下,同时发起大量http请求的问题
上述2、3问题,时间关系,后续优化~