小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

編程技巧:用JQuery異步實現(xiàn)順序加載外部腳本

 CevenCheng 2012-05-24
 

編程技巧:用JQuery異步實現(xiàn)順序加載外部腳本

分類: 編程技巧 368人閱讀 評論(0) 收藏 舉報

用JQuery異步實現(xiàn)順序加載外部腳本

乍看之下是個矛盾的命題,其實并不矛盾。

異步是什么,大家都知道就不說了,說說同步順序加載,也很簡單。就是假如你有A,B,C三資源需要延遲加載,但又要保證A,B,C之間能順序加載,同時不阻塞瀏覽器。
比如:我們需要加載a,b,c三個js 但是C依賴B,B依賴A,就是說在沒有A沒有加載完的前提下,如果B中使用了A中的資源那肯定是會出錯的。C也是如此。這就有了同步順序加載的概念,固使用一般的  (例子都為jQuery,其他AJAX框架應(yīng)該差別不大)

$.ajax(A);
$.ajax(B);
$.ajax(C); 這樣并不能保障ABC會順序加載完,這樣先加載完的會先執(zhí)行。

這樣的解決辦法很多比如直接<script scr="A.js"></script><script scr="B.js" ></script>。。。這樣寫在head或者body中,在IE中這是順序加載的,其他瀏覽器不知道是否這樣,但這會引出一個問題,會阻塞瀏覽器,比如我們打開一個網(wǎng)頁經(jīng)??匆姲灼梁芫貌懦霈F(xiàn)網(wǎng)頁內(nèi)容,這就是在頭部加載了過多的信息,比如CSS,javascript,也許我們可以把<script src=""> 這個方法body標(biāo)簽最下方。這樣可以讓頁面快速呈現(xiàn),但當(dāng)瀏覽器解釋到<script src=""> 時,將依然阻塞瀏覽器,就是感覺卡住的說。
這時需求就出來了,我們希望瀏覽器不被阻塞,那想到的肯定是異步加載資源。我們可以使用jQuery()的異步加載,$.ajax(options),其中有一個選項是async詢問你是否異步,默認是異步,如果你設(shè)置為false 則同步執(zhí)行,但這并不能解決問題,依然阻塞瀏覽器。

很多童鞋應(yīng)該都想到了那我們就用回調(diào)函數(shù)來實現(xiàn)同步順序加載,也就是這樣的形式 :
$.ajax(A,function(){
      $.ajax(B,function(){
          $.ajax(C,function(){
                  .......      
          });
    });
});
哦,問題出來了,太難看了。你需要順序加載的資源過多,而且每加載完一個資源需要執(zhí)行一些處理方法,那么只要這些資源大概上了10個,那么這個縮進就灰常難看了,而且如果你開發(fā)中期需求改變,需要換加一個資源或者刪一個資源就悲劇了,眼睛都看花,而且地球人都知道javascript出錯,是最悲劇的,那個找錯誤啊。

這個問題出自我現(xiàn)在正在寫的一個個人項目,全憑興趣而作,下面給出我的解決方案:

function createLoadComponent() {
 return {
  textContainer : null,
  setContainer: function(container){this.textContainer=container;},
  println : function(data) {
   this.textContainer.text("開始加載" + data + "...");
  },
  dataURLs : new Array(),
  datasCount : 0,
  count:0,
  traverse : function(obj) {
   if (!obj)
    obj = this;
   var dataURL = obj.dataURLs[this.datasCount];
   if (!dataURL)
   {
    for(var i=0;i<obj.onCompletes.length;i+=1)
     obj.onCompletes[i]();
    this.clear(obj);
    return;
   }
   if (dataURL.name&&obj.textContainer)
    obj.println(dataURL.name);
   obj.datasCount += 1;
   $.ajax( {
    url : dataURL.url,
    dataType : dataURL.type ? dataURL.type : "script",
    success : function(data, textStatus) {
     if (dataURL.callBack)
       dataURL.callBack(data);
     obj.traverse(obj);
    }
   });
  },
  eventCount:0,
  ready:function(callBack){
   this.onCompletes[this.eventCount]=callBack;
   this.eventCount+=1;
  },
  onCompletes:new Array(),
  addURL:function(_url,_name,_type,_callBack)
  {
   
   this.dataURLs[this.count]={name:_name,url:_url,type:_type,callBack:_callBack};
   this.count+=1;
   return this;
  },
  clear : function(obj) {
   if(obj)
    obj=this;
   obj==null;
  }
 }
}

這是個異步順序加載器(姑且就這么叫吧)看個使用例子:
var loadComponent = createLoadComponent();   
loadComponent.addURL("/main.jsp","主頁面","html",function(data) {$(document.body).append(data);});   
loadComponent.addURL("/js/comopent/tooltip/jquery.bgiframe.js","標(biāo)簽提示組件");   
loadComponent.addURL("/js/comopent/tooltip/jquery.dimensions.js");   
loadComponent.addURL("/js/comopent/tooltip/jquery.tooltip.min.js");   
loadComponent.addURL("/js/comopent/jquery.validate.js","驗證組件");   
loadComponent.addURL("/js/utils/messages_cn.js");   
loadComponent.addURL("/js/comopent/jquery.cookie.js","cookie組件");   
loadComponent.addURL("/js/comopent/jquery.lazyload.js", "延遲加載組件");   
loadComponent.addURL("/js/comopent/jquery.simplemodal.js","模式框組件");   
loadComponent.addURL("/js/comopent/jquery.quickflip.min.js","Flip組件");   
loadComponent.addURL("/js/mode/UserEntity.js","用戶實體");   
loadComponent.addURL("/js/controller/registController.js","注冊控制器");   
loadComponent.addURL("/js/controller/loginController.js","登錄控制器");   
loadComponent.addURL("/js/controller/errorController.js","錯誤控制器");   
loadComponent.setContainer($("#loadtext"));   
loadComponent.ready(initMain);   
loadComponent.traverse();  
 

下面說下LoadComponent中的方法:
setContainer(container)  加載信息輸出容器,不設(shè)置則不輸出,這里的參數(shù)為JQuery對象,請在執(zhí)行traverse()之前調(diào)用。 
addURL(url,name,type,callBack)添加一個需加載的腳本,只有URL為必要參數(shù);name為添加的資源名字,如果你設(shè)置了輸出容器,則這個名字會在容器中顯示,type為資源類型 html, json,xml,script,由于自己項目原因我這里設(shè)置了默認值為script,callBack這里的回調(diào)方法是加載完該URL所調(diào)用的方法。
ready(callBack) 完成加載所有腳本后所執(zhí)行的回調(diào)方法,如上述initMain就會在所有資源加載完后執(zhí)行,可多次使用ready(callBack)添加多個回調(diào)方法,按添加順序執(zhí)行,請在執(zhí)行traverse()之前調(diào)用。
traverse() 開始同步加載添加的所有URL。執(zhí)行此方法后,會自動執(zhí)行clear() 方法,釋放內(nèi)存,所以,不要在執(zhí)行完traverse()方法后繼續(xù)使用該對象,應(yīng)從新create一個新對象。
注:LoadComponent是基于jquery寫的,所以之前還是需要先讓瀏覽器把jquery加載完,但jquery體積還算是比較小的,無所謂了。

---------------------------------------
其實,你寫的這個方法效率還是不夠高。因為它是順序請求的,而不是并發(fā)請求。
比如要加載a, b, c這3個JS文件,你的做法是a請求完成了再請求b,…… 相當(dāng)于總的時間中還包含了3次http連接建立的時間。

其實要保證運行順序,可以3個文件一起請求。等到都請求完畢后再按順序合并a, b, c,進行執(zhí)行??尚械淖龇ㄖ痪褪窃诿總€文件下載完的回調(diào)函數(shù)里去給一個全局變量加上此文件已加載完的標(biāo)記,同時判斷是否已經(jīng)全部加載完,完了就再按順序?qū)懭肽矰OM對象的innerHTML。

或者弄個更高效更簡潔的辦法:將合并這步操作放到服務(wù)器執(zhí)行,頁面只用請求一次:將a, b, c作為參數(shù)發(fā)給服務(wù)器。但它的壞處是不能緩存。

---------------------------------------
不知道有多少人了解過騰訊一個類似這樣功能的js....很好很強大的。。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多