function getText(time,callback) { setTimeout(function () { callback(time) },time) } var callbackMap={};//记录加载完成的回调 var resMap={};//记录url var loadbackMap={};//记录url 加载完成 var loadedMap={};//记录url 加载完成 var loadedI=-1;//记录url 加载完成位置 var orderI=0;//记录url 当前位置 var orderIMap={};//记录num+url=>orderI var numMap={};//记录url var allUrlArr=[]; var itemArr={}; function exec(item) { console.log('exec',item) if(item.num===1){ } } function loadAll(arr,callback) { var urlArr=[]; for(var i=0;i<arr.length;i++){ if(arr[i]){ urlArr.push(arr[i]) allUrlArr.push(arr[i]) } } //缓存回调 callbackMap[orderI+urlArr.length]=callback; console.log('加载资源',urlArr) for(var i=orderI;i<allUrlArr.length;i++){ console.log(allUrlArr[i],i) loadItem(allUrlArr[i],i,function (item) { itemArr[item.orderI]=item; if(item.orderI-loadedI===1){ synchro(item.orderI) } }) } orderI=orderI+urlArr.length; //同步执行 function synchro(i){ if(i<allUrlArr.length&&itemArr[i]){ loadedI=i; exec(itemArr[i]); delete itemArr[i]; if(callbackMap[i+1]){ callbackMap[i+1](); delete callbackMap[i+1]; } synchro(i + 1); } } } function loadItem(url,orderI,callback) { numMap[url]=numMap[url]||0; numMap[url]++; if(!resMap[url]){ loadbackMap[numMap[url]+'-'+url]=callback; orderIMap[numMap[url]+'-'+url]=orderI; if(numMap[url]===1){ getText(url,function (text) { resMap[url]=text; for(var i=1;i<numMap[url]+1;i++){ if(loadbackMap[i+'-'+url]){ loadbackMap[i+'-'+url]({ url:url, text:text, orderI:orderIMap[i+'-'+url], num:i, }); delete loadbackMap[i+'-'+url]; } } }) } }else{ callback({ url:url, orderI:orderI, text:resMap[url], num:numMap[url] }); } } loadAll([200,100],function (resMap) { console.log(222222) }) loadAll([20,10],function (resMap) { console.log(2222) }) loadAll([200,100],function (resMap) { console.log(222) }) loadAll([20,10],function (resMap) { console.log(22) })
完整lCache.js 先开始加载先执行
!(function () { function getText(url,callback) { var xmlhttp=new XMLHttpRequest(); if(typeof callback!=='function'){ xmlhttp.open("GET",url,false); xmlhttp.send(); return xmlhttp.responseText; } xmlhttp.onreadystatechange=function () { if (this.readyState===4&&this.status===200){ callback(this.responseText) } }; xmlhttp.open("GET",url,true); xmlhttp.send(); } //获取文件key function getFileKey(url) { return url.replace(/(?!w+).w+.(js|css)/,'.$1').replace(/?.+/,'') } window.LCache={ cacheMap:{},//缓存的url curMap:{},//当前的url getText:getText, loadChunk:loadChunk, storagePrefix:'LCache-',//前缀 loadAll:loadAll } var callbackMap={};//记录加载完成的回调 var resMap={};//记录url var loadbackMap={};//记录url 加载完成 var loadedI=-1;//记录url 加载完成位置 var orderI=0;//记录url 当前位置 var orderIMap={};//记录num+url=>orderI var numMap={};//记录url var allUrlArr=[]; var itemArr={}; function loadAll(arr,callback) { var urlArr=[]; for(var i=0;i<arr.length;i++){ var url=arr[i]; if(url){ var key=LCache.storagePrefix+url; var preKey=LCache.cacheMap[getFileKey(key)] if(key===preKey){ resMap[url]=localStorage.getItem(key); } urlArr.push(arr[i]) allUrlArr.push(arr[i]) } } //缓存回调 callbackMap[orderI+urlArr.length]=callback; console.log('加载资源',urlArr) for(var i=orderI;i<allUrlArr.length;i++){ console.log(allUrlArr[i],i) loadItem(allUrlArr[i],i,function (item) { itemArr[item.orderI]=item; if(item.orderI-loadedI===1){ synchro(item.orderI) } }) } orderI=orderI+urlArr.length; //同步执行 function synchro(i){ if(i<allUrlArr.length&&itemArr[i]){ loadedI=i; exec(itemArr[i]); delete itemArr[i]; if(callbackMap[i+1]){ callbackMap[i+1](); delete callbackMap[i+1]; } synchro(i + 1); } } } function loadItem(url,orderI,callback) { numMap[url]=numMap[url]||0; numMap[url]++; if(!resMap[url]){ loadbackMap[numMap[url]+'-'+url]=callback; orderIMap[numMap[url]+'-'+url]=orderI; if(numMap[url]===1){ getText(url,function (text) { resMap[url]=text; for(var i=1;i<numMap[url]+1;i++){ if(loadbackMap[i+'-'+url]){ loadbackMap[i+'-'+url]({ url:url, text:text, orderI:orderIMap[i+'-'+url], num:i, }); delete loadbackMap[i+'-'+url]; } } }) } }else{ callback({ url:url, orderI:orderI, text:resMap[url], num:numMap[url] }); } } //渲染js、css var head = typeof document!='undefined'&&document.getElementsByTagName('head')[0]; function exec(item) { if(item.num===1){ if(/.css/.test(item.url)){ var s = document.createElement("style"); s.setAttribute('data-href',item.url) s.innerHTML = item.text; head.appendChild(s) } else if(/.json/.test(item.url)){ configComponent(JSON.parse(item.text),item.url) }else if(/.js/.test(item.url)){ var script = document.createElement('script'); script.text = item.text; head.appendChild( script ); } var key=LCache.storagePrefix+item.url; var preKey=LCache.cacheMap[getFileKey(key)] //删除旧版本 localStorage.removeItem(preKey); //添加新版本 try { localStorage.setItem(key,item.text); }catch (e) { clearCache(key,item.text); } } } //LCache.js用到的url var UpLCacheLib=localStorage.getItem('UpLCacheLib')||''; LCache.curMap[getFileKey(UpLCacheLib)]=UpLCacheLib; //获取缓存的url for (var i = 0; i < localStorage.length; i++) { var key = localStorage.key(i); if(key.indexOf(LCache.storagePrefix)===0){ if(getFileKey(UpLCacheLib)===getFileKey(key)&&UpLCacheLib!==key){ localStorage.removeItem(key); }else{ LCache.cacheMap[getFileKey(key)]=key; } } } //渲染js、css var head = typeof document!='undefined'&&document.getElementsByTagName('head')[0]; function exec(item){ if(item.num===1){ if(/.css/.test(item.url)){ var s = document.createElement("style"); s.setAttribute('data-href',item.url) s.innerHTML = item.text; head.appendChild(s) } else if(/.json/.test(item.url)){ configComponent(JSON.parse(item.text),item.url) }else if(/.js/.test(item.url)){ var script = document.createElement('script'); script.text = item.text; head.appendChild( script ); } var key=LCache.storagePrefix+item.url; var preKey=LCache.cacheMap[getFileKey(key)] //删除旧版本 localStorage.removeItem(preKey); //添加新版本 try { localStorage.setItem(key,item.text); }catch (e) { clearCache(key,item.text); } } } //清除缓存 function clearCache(key,text) { if(key&&text){ console.log('clearCache') for(var nkey in LCache.cacheMap){ if(!LCache.curMap[nkey]){ localStorage.removeItem(LCache.cacheMap[nkey]); } } try { localStorage.setItem(key,text); }catch (e) { clearCache() } }else{ console.log('clearAllPreCache') for(var key in LCache.cacheMap){ localStorage.removeItem(LCache.cacheMap[key]); } } } //执行增量包 function execChunk(s1,chunk){ var ns=''; for(var i=0;i<chunk.length;i++){ var arr=chunk[i]; if(arr[0]===0){ ns=ns+s1.substr(arr[1],arr[2]) }else if(arr[0]===1){ ns=ns+arr[1] } } return ns; } //加载增量包 function loadChunk(curVersion,name) { var chunkVersion=localStorage.getItem(name); localStorage.setItem(name,curVersion); if(chunkVersion&&chunkVersion!==curVersion){ try { var text=getText('chunk/'+chunkVersion+'-'+curVersion+'.json') var chunkArr=JSON.parse(text); for(var i=0;i<chunkArr.length;i++){ var obj=chunkArr[i] var preKey=LCache.storagePrefix+obj.a; var key=LCache.storagePrefix+obj.b; var s1=localStorage.getItem(preKey); if(s1){ var s2=execChunk(s1,obj.c); LCache.cacheMap[getFileKey(preKey)]=key; localStorage.removeItem(preKey); localStorage.setItem(key,s2); } } }catch (e) { } } } //配置组件包 function configComponent(assetsJSON,relaUrl) { Vue.$component=Vue.$component||{}; if(/^http/.test(relaUrl)){ relaUrl=relaUrl.replace(//webpack.+$/,'/') }else{ relaUrl=''; } for(var name in assetsJSON){ if(name&&typeof assetsJSON[name]==='object'){ Vue.component(name,getComponent(name)) } } //注册组件 function getComponent(name) { var loadArr=[] if(typeof assetsJSON[name]==='object'){ if(typeof assetsJSON[name].css==='string'){ loadArr.push(/^w/.test(assetsJSON[name].css)&&relaUrl?relaUrl+assetsJSON[name].css:assetsJSON[name].css) } if(typeof assetsJSON[name].js==='string'){ loadArr.push(/^w/.test(assetsJSON[name].js)&&relaUrl?relaUrl+assetsJSON[name].js:assetsJSON[name].js) } } return function (resolve) { LCache.loadAll(loadArr,function () { if(typeof Vue.$component[name]==='function'){ Vue.$component[name](resolve) }else if(typeof Vue.$component[name]==='object'){ resolve(Vue.$component[name]) } }) } } } })()