function toParamString(obj: any) {
// string, number, boolean
if (typeof obj !== 'object') {
return JSON.stringify(obj);
}
// object , array
const keys = Object.keys(obj);
const entities = keys.sort().map((key) => {
let value = obj[key];
if (value === undefined) {
value = null;
} else if (typeof value === 'object') {
value = toParamString(obj);
}
return `${key}$$$$${value}`;
});
return entities.join('@@@@');
}
class BatchRequest {
constructor({deferMs = 100, useCache = true, onBatchRequest}) {
this.useCache = useCache;
this.deferMs = deferMs;
this.onBatchRequest = onBatchRequest;
this.reqCtxList = [];
this.tryRequesTimeout = 0;
this.cacheMap = {};
}
createDefer(cacheKey) {
let _resolve
let _reject
const promise = new Promise((resolve, reject) => {
_resolve = resolve
_reject = reject
});
// 启用cache
let _resolve2 = _resolve;
if (this.useCache) {
_resolve2 = (data)=>{
this.cacheMap[cacheKey] = data;
_resolve(data);
}
}
return {
promise,
resolve: _resolve2,
reject: _reject,
}
}
tryRequest(){
if (this.tryRequesTimeout) {
clearTimeout(this.tryRequesTimeout);
this.tryRequesTimeout = 0;
}
this.tryRequesTimeout = setTimeout(()=> {
const reqCtxList = this.reqCtxList;
this.reqCtxList = []; // 下次再请求,就用新的。
this.tryRequesTimeout = 0; // 下次再请求,就用新的。
this.onBatchRequest(reqCtxList);
}, this.deferMs);
}
doRequest(param){
const cacheKey = toParamString(param);
// 本身有缓存。直接返回。
if (this.useCache && this.cacheMap[cacheKey]) {
const ss = this.cacheMap[cacheKey];
return Promise.resolve(ss);
}
const defer = this.createDefer(cacheKey);
const ctx = {param, defer};
this.reqCtxList.push(ctx);
this.tryRequest();
return defer.promise;
}
}
const batchRequestInstanceMap = {};
function getBatchRequest(name, onBatchRequest){
let instance = batchRequestInstanceMap[name];
if (!instance) {
instance = new BatchRequest({
onBatchRequest
});
batchRequestInstanceMap[name] = instance;
}
return instance;
}
export {
getBatchRequest,
BatchRequest
}