'use strict'; /* 异步数据模块加载器 功能 1、加载器存在 主任务、副任务、子任务 newRequire 表示加载主任务,主任务并发执行,newRequire(param1),执行主任务的时候,暂停副任务,主任务结束后,再执行副任务。 runFreeRequest 表示加载副任务,任务放队列,主任务结束后,副任务按顺序执行 require表示加载子任务,rule匹配后,执行ruleFunc(param1) 2、执行过程为:传入数据模块,匹配rule,执行ruleFunc,返回结果 param1表示模块数据,可为 String、Object、Number、Array, onRequest表示定义规则,onRequest(rule,ruleFunc) rule表示模块规则,可为 String、Function、Number,匹配param1则返回true,然后运行规则函数 ruleFunc表示规则函数,可为AsyncFunction、Function,返回结果 3、生命周期 相同的param1在同一个newRequire周期中,只会加载一次,默认缓存时间为0,也就是在下一个newRequire之前会被清理调缓存。 4、设置param1缓存时间 onRequest(rule,ruleFunc,0) 定义符合规则的所有模块,无缓存,优先级底 this.setCacheTime(param1,1000) 在ruleFunc函数内调用,设置缓存1秒,优先级高 demo //主进程加载器 const mainLoader=new AMDLoader(); mainLoader.defineArr();//数组规则 mainLoader.defineObj();//对象规则 //定义method模块规则 const onRequest=mainLoader.onRequest.bind(mainLoader); onRequest(function (param1) { if(this.isType(param1,'Object')&¶m1.method){ const key=JSON.stringify(param1); if(key.length>200){ return cryptoPassFunc(key) } return true; } },async function (param1) { const func=methodMap[param1.method]||getMethod(param1.method); if(func){ return await func.call(this,param1); }else{ throw 'method不存在'; } },300000);//设置method缓存时间5分钟 主任务 mainLoader.newRequire([ { method:'random', needFlag:true, t:1 }, { method:'random', } ]).then(function (res) { console.log(res) }).catch(function (e) { console.log(e) }) =》[ { flag: 'S', startTime: 1585545204173, data: 1585545204475, endTime: 1585545204475 }, 1585545204777 ] 副任务 mainLoader.runFreeRequest({ method:'task1', }).then(function (res) { console.log(res) }).catch(function (e) { console.log(e) }) =》完成任务 [ 'task1:1585547219188', 'clearMoreCache:59' ] */ //主任务 class NRequire { isType(obj,str){ return Object.prototype.toString.call(obj) === '[object '+str+']'; } constructor(loader){ this.loader=loader; this.cacheMap={};//缓存 this.startTimeMap={}; this.endTimeMap={}; //获取没过期的缓存 const time=new Date().getTime(); for(let url in loader.cacheMap){ if(this.isType(loader.moduleCacheTime[url],'Number')&&time<loader.endTimeMap[url]+loader.moduleCacheTime[url]){ this.cacheMap[url]=loader.cacheMap[url]; }else{ delete loader.moduleCacheTime[url]; loader.clearCache(url) } } } //加载模块 async require(param1){ //是否匹配到规则 const {key,index}=this.loader.matchRule(param1); //需要缓存 if(index>-1){ let res; const rulFunc=this.loader.ruleFuncs[index]; const rulTime=this.loader.ruleCacheTimes[index]; //匹配缓存,同时缓存在有效期 if(typeof this.cacheMap[key]!=='undefined'){ return this.cacheMap[key]; } if(this.isType(rulTime,'Number')){ this.loader.moduleCacheTime[key]=rulTime; } if(this.isType(rulFunc,'AsyncFunction')){ res=await this.loader.startKey(key); if(!res){ this.startTimeMap[key]=new Date().getTime(); try { res=await rulFunc.call(this,param1); }catch (e) { this.loader.endKey(key,res) throw e; } this.cacheMap[key] = res; //缓存时间 this.endTimeMap[key]=new Date().getTime(); } this.loader.endKey(key,res) }else if(this.isType(rulFunc,'Function')){ res=rulFunc.call(this,param1); this.cacheMap[key] = res; }else{ res=rulFunc; this.cacheMap[key] = res; } //缓存放入loader中 if(this.loader.moduleCacheTime[key]>0){ this.loader.cacheMap[key]=res; this.loader.startTimeMap[key]=this.startTimeMap[key]; this.loader.endTimeMap[key]=this.endTimeMap[key]; } return res; }else{ return param1; } } //设置模块缓存时间 setCacheTime(param1,cacheTime){ const item=this.loader.matchRule(param1); if(this.isType(cacheTime,'Number')){ this.loader.moduleCacheTime[item.key]=cacheTime; } } } //AMD模块缓存加载器 class AMDLoader{ //设置模块缓存时间 setCacheTime(param1,cacheTime){ const item=this.matchRule(param1); if(this.isType(cacheTime,'Number')){ this.moduleCacheTime[item.key]=cacheTime; } } isType(obj,str){ return Object.prototype.toString.call(obj) === '[object '+str+']'; } async startKey(key){ this.willI[key]=this.willI[key]||0; this.curI[key]=this.curI[key]||0; this.willI[key]++; if(this.willI[key]>this.curI[key]+1){ return await new Promise((res)=> { this.loadBack[''+key+this.willI[key]]=res; }) } } endKey(key,res){ if(this.curI[key]<this.willI[key]){ this.curI[key]++; while (this.curI[key]<this.willI[key]){ this.curI[key]++; this.loadBack[''+key+this.curI[key]](res); delete this.loadBack[''+key+this.curI[key]]; } } } constructor(){ //配置 this.rules=[]; this.ruleFuncs=[]; this.ruleCacheTimes=[]; this.cacheMap={};//永久缓存,最大100 this.moduleCacheTime={};//临时缓存时间 this.startTimeMap={}; this.endTimeMap={}; this.nearTimeMap={}; //异步工具 this.willI={}; this.curI={}; this.loadBack={}; this.running=0; this.actionArr=[]; } //主任务 async newRequire(param1){ this.running++; const nQest=new NRequire(this);//主任务 try { const res=await nQest.require(param1); this.running--; return res; }catch (e) { let obj=this.isType(e,'Object')&&e.logType==='_error'?e:{ msg:e, logType:'error', bizData:param1, }; this.running--; if(this.running===0){ //执行副任务 this.runFreeRequest() } //内部错误 // this.log(obj) throw obj.msg; } } //副任务 async runFreeRequest(param1){ if(param1){ this.actionArr.push(param1); } if(this.running>0){ console.log('存在主任务'); return [] } const arr=[] while (this.running===0&&this.actionArr.length>0){ const bizData=this.actionArr.shift(); const nQest=new NRequire(this);//主任务 try { const res=await nQest.require(bizData) arr.push(res); }catch (e) { arr.push(e); } } return arr } clearCache(key){ delete this.cacheMap[key]; delete this.nearTimeMap[key]; delete this.startTimeMap[key]; delete this.endTimeMap[key]; } onRequest(rule,ruleFunc,cacheTime){ this.rules.push(rule); this.ruleFuncs.push(ruleFunc); this.ruleCacheTimes.push(cacheTime); } //命中规则 matchRule(param1){ let key;//key必然是个字符或者数字 if(this.isType(param1,'String')){ key=param1 }else if(this.isType(param1,'Object')){ key=JSON.stringify(param1) }else if(this.isType(param1,'Array')){ key=JSON.stringify(param1) }else if(this.isType(param1,'Number')){ key=JSON.stringify(param1) } let index=-1; let keyback;//params 返回值 for(let i=this.rules.length-1;i>-1;i--){ const rule=this.rules[i]; if(this.isType(rule,'Function')){ keyback=rule.call(this,param1); if(keyback){ index=i; break; } }else if(this.isType(rule,'String')||this.isType(rule,'Number')){ keyback=rule; if(param1===rule){ index=i; break; } } } if(index>-1){ if(this.isType(keyback,'String')){ key=keyback; } } return { index:index, key:key, keyback:keyback, } } log(obj){ console.log('发邮件',obj) if(obj.logType==='_error'){ }else if(obj.logType==='error'){ } } //定义数组加载,[name1,name2] defineArr(){ this.onRequest(function (param1) { if(this.isType(param1,'Array')){ return true; } },async function (param1) { const arr1=[] for(let i=0;i<param1.length;i++){ const res=await this.require(param1[i]) arr1.push(res) } return arr1 }) } //定义对象加载 {name1:'name1',name2:'name2'} defineObj(){ this.onRequest(function (param1) { if(this.isType(param1,'Object')){ return true; } },async function (param1) { const nobj={}; const arr1=[] const arr2=[] for(let k in param1){ arr1.push(k); arr2.push(this.require(param1[k])); } const arr3=await Promise.all(arr2); for(let i=0;i<arr1.length;i++){ nobj[arr1[i]]=arr3[i]; } return nobj }) } } module.exports=AMDLoader;