欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
非阻塞式JavaScript腳本介紹

非阻塞式JavaScript腳本介紹

2011-01-30

JavaScript 傾向于阻塞瀏覽器某些處理過(guò)程,如HTTP 請求和界面刷新,這是開(kāi)發(fā)者面臨的最顯著(zhù)的性能問(wèn)題。保持JavaScript文件短小,并限制HTTP請求的數量,只是創(chuàng )建反應迅速的網(wǎng)頁(yè)應用的第一步。一個(gè)應用程序所包含的功能越多,所需要的JavaScript 代碼就越大,保持源碼短小并不總是一種選擇。盡管下載一個(gè)大JavaScript 文件只產(chǎn)生一次HTTP 請求,卻會(huì )鎖定瀏覽器一大段時(shí)間。為避開(kāi)這種情況,你需要向頁(yè)面中逐步添加JavaScript,某種程度上說(shuō)不會(huì )阻塞瀏覽器。非阻塞腳本的秘密在于,等頁(yè)面完成加載之后,再加載JavaScript 源碼。從技術(shù)角度講,這意味著(zhù)在window 的load 事件發(fā)出之后開(kāi)始下載代碼。有三種方法可以實(shí)現這種效果。

延期腳本

HTML 4 為<script>標簽定義了一個(gè)擴展屬性:defer。這個(gè)defer 屬性指明元素中所包含的腳本不打算修改DOM,因此代碼可以稍后執行。defer 屬性只被Internet Explorer 4 和Firefox 3.5 更高版本的瀏覽器所支持,它不是一個(gè)理想的跨瀏覽器解決方案。在其他瀏覽器上,defer 屬性被忽略,<script>標簽按照默認方式被處理(造成阻塞)。如果瀏覽器支持的話(huà),這種方法仍是一種有用的解決方案。示例如下:

1<script type="text/javascript" src="file1.js" defer></script>

一個(gè)帶有defer 屬性的<script>標簽可以放置在文檔的任何位置。對應的JavaScript 文件將在<script>被解析時(shí)啟動(dòng)下載,但代碼不會(huì )被執行,直到DOM 加載完成。(在onload 事件句柄被調用之前)。當一個(gè)defer的JavaScript 文件被下載時(shí),它不會(huì )阻塞瀏覽器的其他處理過(guò)程,所以這些文件可以與頁(yè)面的其他資源一起并行下載。任何帶有defer 屬性的<script>元素在DOM 加載完成之前不會(huì )被執行,不論是內聯(lián)腳本還是外部腳本文件,都是這樣。下面的例子展示了defer 屬性如何影響腳本行為:

01<html>
02      <head>
03            <title>Script Defer Example</title>
04      </head>
05      <body>
06            <script defer>
07                  alert("defer");
08            </script>
09            <script>
10                  alert("script");
11            </script>
12            <script>
13                  window.onload = function(){
14            alert("load");
15            };
16            </script>
17      </body>
18</html>

這些代碼在頁(yè)面處理過(guò)程中彈出三個(gè)對話(huà)框。如果瀏覽器不支持defer 屬性,那么彈出對話(huà)框的順序是"defer","script"和"load"。如果瀏覽器支持defer 屬性,那么彈出對話(huà)框的順序是"script","defer"和"load"。注意,標記為defer 的<script>元素不是跟在第二個(gè)后面運行,而是在onload 事件句柄處理之前被調用。如果你的目標瀏覽器只包括Internet Explorer 和Firefox 3.5,那么defer 腳本確實(shí)有用。如果你需要支持跨領(lǐng)域的多種瀏覽器,那么還有更一致的實(shí)現方式。

動(dòng)態(tài)腳本元素

文檔對象模型(DOM)允許你使用JavaScript 動(dòng)態(tài)創(chuàng )建HTML 的幾乎全部文檔內容。其根本在于,<script>元素與頁(yè)面其他元素沒(méi)有什么不同:引用變量可以通過(guò)DOM 進(jìn)行檢索,可以從文檔中移動(dòng)、刪除,也可以被創(chuàng )建。一個(gè)新的<script>元素可以非常容易地通過(guò)標準DOM 函數創(chuàng )建:

1var script = document.createElement ("script");
2script.type = "text/javascript";
3script.src = "file1.js";
4document.getElementsByTagName_r("head")[0].appendChild(script);

新的<script>元素加載file1.js 源文件。此文件當元素添加到頁(yè)面之后立刻開(kāi)始下載。此技術(shù)的重點(diǎn)在于:無(wú)論在何處啟動(dòng)下載,文件的下載和運行都不會(huì )阻塞其他頁(yè)面處理過(guò)程。你甚至可以將這些代碼放在<head>部分而不會(huì )對其余部分的頁(yè)面代碼造成影響(除了用于下載文件的HTTP 連接)。

當文件使用動(dòng)態(tài)腳本節點(diǎn)下載時(shí),返回的代碼通常立即執行(除了Firefox 和Opera,他們將等待此前的所有動(dòng)態(tài)腳本節點(diǎn)執行完畢)。當腳本是"自運行"類(lèi)型時(shí)這一機制運行正常,但是如果腳本只包含供頁(yè)面其他腳本調用調用的接口,則會(huì )帶來(lái)問(wèn)題。這種情況下,你需要跟蹤腳本下載完成并準備妥善的情況??梢允褂脛?dòng)態(tài)<script>節點(diǎn)發(fā)出事件得到相關(guān)信息。

Firefox, Opera, Chorme 和Safari 3+會(huì )在<script>節點(diǎn)接收完成之后發(fā)出一個(gè)load 事件。你可以監聽(tīng)這一事件,以得到腳本準備好的通知:

1var script = document.createElement ("script")
2script.type = "text/javascript";
3//Firefox, Opera, Chrome, Safari 3+
4      script.onload = function(){
5      alert("Script loaded!");
6};
7script.src = "file1.js";
8document.getElementsByTagName("head")[0].appendChild(script);

Internet Explorer 支持另一種實(shí)現方式,它發(fā)出一個(gè)readystatechange 事件。<script>元素有一個(gè)readyState屬性,它的值隨著(zhù)下載外部文件的過(guò)程而改變。readyState 有五種取值:

  • "uninitialized"默認狀態(tài)
  • "loading"下載開(kāi)始
  • "loaded"下載完成
  • "interactive"下載完成但尚不可用
  • "complete"所有數據已經(jīng)準備好

微軟文檔上說(shuō),在<script>元素的生命周期中,readyState 的這些取值不一定全部出現,但并沒(méi)有指出哪些取值總會(huì )被用到。實(shí)踐中,我們最感興趣的是"loaded"和"complete"狀態(tài)。Internet Explorer 對這兩個(gè)readyState 值所表示的最終狀態(tài)并不一致,有時(shí)<script>元素會(huì )得到"loader"卻從不出現"complete",但另外一些情況下出現"complete"而用不到"loaded"。最安全的辦法就是在readystatechange 事件中檢查這兩種狀態(tài),并且當其中一種狀態(tài)出現時(shí),刪除readystatechange 事件句柄(保證事件不會(huì )被處理兩次):

01var script = document.createElement("script")
02script.type = "text/javascript";
03//Internet Explorer
04script.onreadystatechange = function(){
05      if (script.readyState == "loaded" || script.readyState == "complete"){
06            script.onreadystatechange = null;
07            alert("Script loaded.");
08      }
09};
10script.src = "file1.js";
11document.getElementsByTagName("head")[0].appendChild(script);

大多數情況下,你希望調用一個(gè)函數就可以實(shí)現JavaScript 文件的動(dòng)態(tài)加載。下面的函數封裝了標準實(shí)現和IE 實(shí)現所需的功能:

01function loadScript(url, callback){
02        var script = document.createElement ("script")
03        script.type = "text/javascript";
04        if (script.readyState){ //IE
05              script.onreadystatechange = function(){
06                    if (script.readyState == "loaded" || script.readyState == "complete"){
07                          script.onreadystatechange = null;
08                          callback();
09                    }
10             };
11        } else { //Others
12              script.onload = function(){
13              callback();
14        };
15  }
16  script.src = url;
17  document.getElementsByTagName("head")[0].appendChild(script);
18  }

此函數接收兩個(gè)參數:JavaScript 文件的URL,和一個(gè)當JavaScript 接收完成時(shí)觸發(fā)的回調函數。屬性檢查用于決定監視哪種事件。最后一步,設置src 屬性,并將<script>元素添加至頁(yè)面。此loadScript()函數使用方法如下:

1loadScript("file1.js", function(){
2        alert("File is loaded!");
3  });

你可以在頁(yè)面中動(dòng)態(tài)加載很多JavaScript 文件,但要注意,瀏覽器不保證文件加載的順序。所有主流瀏覽器之中,只有Firefox 和Opera 保證腳本按照你指定的順序執行。其他瀏覽器將按照服務(wù)器返回它們的次序下載并運行不同的代碼文件。你可以將下載操作串聯(lián)在一起以保證他們的次序,如下:

1loadScript("file1.js", function(){
2        loadScript("file2.js", function(){
3              loadScript("file3.js", function(){
4                    alert("All files are loaded!");
5              });
6        });
7  });

此代碼等待file1.js 可用之后才開(kāi)始加載file2.js,等f(wàn)ile2.js 可用之后才開(kāi)始加載file3.js。雖然此方法可行,但如果要下載和執行的文件很多,還是有些麻煩。如果多個(gè)文件的次序十分重要,更好的辦法是將這些文件按照正確的次序連接成一個(gè)文件。獨立文件可以一次性下載所有代碼(由于這是異步進(jìn)行的,使用一個(gè)大文件并沒(méi)有什么損失)。

動(dòng)態(tài)腳本加載是非阻塞JavaScript 下載中最常用的模式,因為它可以跨瀏覽器,而且簡(jiǎn)單易用。

使用XMLHttpRequest(XHR)對象

此技術(shù)首先創(chuàng )建一個(gè)XHR 對象,然后下載JavaScript 文件,接著(zhù)用一個(gè)動(dòng)態(tài)<script>元素將JavaScript 代碼注入頁(yè)面。下面是一個(gè)簡(jiǎn)單的例子:

01var xhr = new XMLHttpRequest();
02xhr.open("get", "file1.js", true);
03xhr.onreadystatechange = function(){
04      if (xhr.readyState == 4){
05            if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
06                  var script = document.createElement ("script");
07                  script.type = "text/javascript";
08                  script.text = xhr.responseText;
09                  document.body.appendChild(script);
10            }
11      }
12};
13xhr.send(null);

此代碼向服務(wù)器發(fā)送一個(gè)獲取file1.js 文件的GET 請求。onreadystatechange 事件處理函數檢查readyState是不是4,然后檢查HTTP 狀態(tài)碼是不是有效(2XX 表示有效的回應,304 表示一個(gè)緩存響應)。如果收到了一個(gè)有效的響應,那么就創(chuàng )建一個(gè)新的<script>元素,將它的文本屬性設置為從服務(wù)器接收到的responseText 字符串。這樣做實(shí)際上會(huì )創(chuàng )建一個(gè)帶有內聯(lián)代碼的<script>元素。一旦新<script>元素被添加到文檔,代碼將被執行,并準備使用。這種方法的主要優(yōu)點(diǎn)是,你可以下載不立即執行的JavaScript 代碼。由于代碼返回在<script>標簽之外(換句話(huà)說(shuō)不受<script>標簽約束),它下載后不會(huì )自動(dòng)執行,這使得你可以推遲執行,直到一切都準備好了。另一個(gè)優(yōu)點(diǎn)是,同樣的代碼在所有現代瀏覽器中都不會(huì )引發(fā)異常。此方法最主要的限制是:JavaScript 文件必須與頁(yè)面放置在同一個(gè)域內,不能從CDNs 下載(CDN 指"內容投遞網(wǎng)絡(luò )(Content Delivery Network)",大型網(wǎng)頁(yè)通常不采用XHR 腳本注入技術(shù)。

推薦的向頁(yè)面加載大量JavaScript 的方法分為兩個(gè)步驟:第一步,包含動(dòng)態(tài)加載JavaScript 所需的代碼,然后加載頁(yè)面初始化所需的除JavaScript 之外的部分。這部分代碼盡量小,可能只包含loadScript()函數,它下載和運行非常迅速,不會(huì )對頁(yè)面造成很大干擾。當初始代碼準備好之后,用它來(lái)加載其余的JavaScript。例如:

1<script type="text/javascript" src="loader.js"></script>
2<script type="text/javascript">
3      loadScript("the-rest.js", function(){
4            Application.init();
5      });
6</script>

將此代碼放置在body 的關(guān)閉標簽</body>之前。這樣做有幾點(diǎn)好處:首先,像前面討論過(guò)的那樣,這樣做確保JavaScript 運行不會(huì )影響頁(yè)面其他部分顯示。其次,當第二部分JavaScript 文件完成下載,所有應用程序所必須的DOM 已經(jīng)創(chuàng )建好了,并做好被訪(fǎng)問(wèn)的準備,避免使用額外的事件處理(例如window.onload)來(lái)得知頁(yè)面是否已經(jīng)準備好了。另一個(gè)選擇是直接將loadScript()函數嵌入在頁(yè)面中,這可以避免另一次HTTP 請求。例如:

01<script type="text/javascript">
02      function loadScript(url, callback){
03            var script = document.createElement ("script")
04            script.type = "text/javascript";
05            if (script.readyState){ //IE
06                  script.onreadystatechange = function(){
07                        if (script.readyState == "loaded" ||
08                        script.readyState == "complete"){
09                              script.onreadystatechange = null;
10                              callback();
11                        }
12                  };
13            } else { //Others
14                  script.onload = function(){
15                  callback();
16                  };
17            }
18            script.src = url;
19            document.getElementsByTagName_r("head")[0].appendChild(script);
20      }
21      loadScript("the-rest.js", function(){
22            Application.init();
23      });
24</script>

如果你決定使用這種方法,建議你使用''YUI Compressor''或者類(lèi)似的工具將初始化腳本縮小到最小字節尺寸。一旦頁(yè)面初始化代碼下載完成,你還可以使用loadScript()函數加載頁(yè)面所需的額外功能函數。

隨機文章推薦


網(wǎng)站分類(lèi)
?

注:如需轉載本文,請注明出處(原文鏈接),謝謝。更多精彩內容,請進(jìn)入簡(jiǎn)明現代魔法首頁(yè)。

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
高性能Javascript
一篇文章帶你搞定JavaScript 性能調優(yōu)
JS的阻塞特性
JavaScript的性能優(yōu)化:加載和執行
頁(yè)面無(wú)阻塞加載研究
JavaScript 在 Promise.then 方法里返回新的 Promise
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久