异步加载text资源,加载一次执行一次链式回调

Posted caoke

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了异步加载text资源,加载一次执行一次链式回调相关的知识,希望对你有一定的参考价值。

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])
          }
        })
      }
    }
  }
})()

 

以上是关于异步加载text资源,加载一次执行一次链式回调的主要内容,如果未能解决你的问题,请参考以下文章

回调函数的使用场合

ztree 异步加载 节点点击事件无触发 只有第一次刷新的时候才加载!

Node.js链式回调

页面大量的节点Dtree一次加载很慢,多次弹出提示框,需点击否多次,才加载完,怎么用ajax异步加载节点!

requireJS异步加载

大数据第五天作业