http://www.aygfsteel.com/ebecket 返還網
          隨筆-140  評論-11  文章-131  trackbacks-0

          無阻塞下載腳本

          原文作者:Nicholas C. Zakas
          原文鏈接:Loading JavaScript without blocking
          譯文:
          我看了Steve Souder的博文scripts without blocking 在這篇博文中他提到動態的創建一個script元素同時為他分配一個src的屬性會促成下載這個js文件而不阻塞其他的下載或者頁面的其他進程。他的博文 缺少一個如何實現這種方式的例子。所以我想我。我想大多數開發者試圖使用javascript腳本庫來實現這種需求(我首先想到了YUI的Get utility)但是很有必要討論一下這個技術的本質。
          無阻塞的加載腳本的基本實現方式非常直接。
          var scripts=document.createElement('script');
                      script.type="text/javascript";
                      script.src="file.js";
                      document.body.appendChild(scripts);
          看 起來就是這么的簡單,你創建了一個新的dom元素,給他它分配相應的屬性同時把它添加到頁面中。這段代碼有兩個方面需要注意。javascript文件直 到script節點添加到document中才開始下載。這一點和動態的創建一個img元素,為這個元素分配一個src屬性這時候加載已經開始即使該節點 沒有添加到document中。第二點需要注意的是你既能在<head>中添加該script節點又能在<body>中添加。這 個無關緊要。這一切的結果就是動態的加載一個javascript文件而不阻塞頁面。

          當然,你可能同時也想知道什么時候 javascript文件完全被加載好和執行,同時這也是事情復雜之所在。大多數modern的瀏覽器(firefox ,safari,opera,chrome)對于scrpt元素有一個load的事件句柄。這是一個確定腳本是否加載好的簡單方式。
          //Firefox, Safari, Chrome, and Opera
                      var scripts=document.createElement('script');
                      script.type="text/javascript";
                      script.src="file.js";
                     
                      scripts.onload=function(){
                          alert('Script is loaded!')
                      }
          document.body.appendChild(scripts);
          真 正的問題出現在ie中,ie使用readyState屬性表明script所處于的狀態readystatechange事件句柄表明屬性改變的時間。在 這里readyState不和xmlHttpRequest對象中一樣,這里一系列的狀態值不是一個數字。在這里,readyState是五個可能是屬性 值。
          *“uninitialized” 原始的狀態。
          *"loading"下載開始
          *"loaded"下載完成
          *"interactive"數據處在一種不完全可用
          *"complete"所有的數據都可以被使用
          即 使MSDN documentation表示這些是readyState可用的值,實際上,你不可能看到所有的狀態。該文檔同時說明其他的元素也支持 readyState同時留給我們一個相當晦澀對于readyState期望值的描述:一個對象的state首先被初始化為unintialized,然 后是loading,當數據加載完成,狀態變為loaded然后是interactive最后是complete狀態。

          對象所有經歷的狀態取決于這個對象。一個對象可以跳過某個狀態(比如說,interactive)如果這個狀態沒有被應到到這個對象。
          更 奇怪的是最后的狀態不總是complete。有些時候,readState停止在loaded狀態而不過渡到complete狀態。同時有些時候會跳過 loaded狀態。最好的解決方式是檢查兩個readState值同時在兩個事件中移除事件處理這樣可以確保你不會處理兩次下載。
          var scripts=document.createElement('script');
                      script.type="text/javascript";
                      script.src="file.js";
                      document.body.appendChild(scripts);
                      scripts.onreadystatechange=function(){
                          if(readyState=="loaded"||readyState=="complete"){
                              scripts.onreadystatechange=null;
                              alert('script is loaded!')
                          }
                      }
                      document.body.appendChild(scripts);
          你能完美的封裝這兩個解決方式從而創造一個跨瀏覽器的函數動態加載腳本。
          function loadScript(url,callback){
                          var script=document.createElement('script');
                          script.type="text/javascript";
                          if(script.readyState){
                              script.onreadystatechange=function(){
                                  if(readyState=="loaded" || readyState=="complete"){
                                      script.onreadystatechange=null;
                                      callback();
                                  }
                              }
                          }else{
                              script.onload=function(){
                                  callback();
                              }
                          }
                          script.src=url;
                          document.body.appendChild(script);
          使用這個函數的時候,只是傳入一個腳本所在的地址然后在加載好之后調用一個回調函數。
          loadScript("http://yui.yahooapis.com/2.7.0/build/yahoo/yahoo-min.js",
              function(){
                  YAHOO.namespace("mystuff");

              //more...
          });

          以這種方式加載腳本避免腳本阻塞頁面中其他資源的下載或者阻止渲染。對于提高性能這是一種相當有用的技術。真正cool的事情是YUI3構建了一個完美的無阻塞下載方式。所有你需要做的就是下載一個大約20kb的seed文件同時說明你需要下載的其他資源文件。比如這樣
          YUI().use("dom", function(Y){
              Y.DOM.addClass(document.body, "active");
          });

          實際上,YUI構建了一個合適的url以便下載dom模塊,當代碼可執行時自動執行回調函數。這樣通過異步下載其余的腳本文件從而優化了整個頁面下載的時間。
          無阻塞的下載一個腳本是一個需要明白的重要技術同時在關注頁面下載性能的web應用程序中應用。javascript 阻塞是整個用戶體驗降低,但是我們已經可以對阻塞說不了。
          posted on 2010-02-28 23:54 becket_zheng 閱讀(286) 評論(0)  編輯  收藏 所屬分類: 網頁web前端技術
          主站蜘蛛池模板: 正镶白旗| 斗六市| 芦溪县| 旌德县| 中阳县| 洪江市| 玛曲县| 池州市| 南川市| 大关县| 景泰县| 内丘县| 南京市| 贞丰县| 上林县| 庆元县| 阿克| 丰宁| 洛宁县| 菏泽市| 巴林左旗| 镇巴县| 全南县| 兴安盟| 来凤县| 明水县| 红河县| 喀喇沁旗| 博罗县| 垣曲县| 枣庄市| 三穗县| 静宁县| 扎兰屯市| 临澧县| 淳化县| 永善县| 九龙坡区| 夹江县| 宾阳县| 资兴市|