搜尋
首頁web前端js教程JavaScript非同步載入淺析_javascript技巧

前言

關於JavaScript腳本載入的問題,相信大家碰到很多。主要在幾個點-

1> 同步腳本與非同步腳本帶來的檔案載入、檔案依賴及執行順序問題
2> 同步腳本與非同步腳本帶來的效能最佳化問題


深入理解腳本載入相關的方方面面問題,不僅利於解決實際問題,更有利於對效能最佳化的掌握並執行。
 
先看隨便一個script標籤程式碼——


複製程式碼 程式碼如下:



如果放在

上面,會阻塞所有頁面渲染工作,使得使用者在腳本載入完畢並執行完畢之前一直處於「白屏死機」狀態。而最後的打腳本只會讓使用者看到毫無生命力的靜態頁面,原本應該進行客戶端渲染的地方卻散佈著不起作用的控制項和空空如也的方格。拿一個測試用例——

複製程式碼 程式碼如下:




   
    非同步載入script
   


   
我是內容物

    JavaScript非同步載入淺析_javascript技巧


其中,test.js中的內容—


複製程式碼 程式碼如下:

alert('我是head裡面的腳本程式碼,執行這裡的js之後,才開始進行body的內容渲染!');


我們會看到,alert是一個暫停點,此時,頁面是空白的。但要注意,此時整個頁面已經載入完畢,如果body中包含某些src屬性的標籤(如上面的img標籤),此時瀏覽器已經開始載入相關內容了。總之要注意-js引擎和渲染引擎的工作時機是互斥的(一些書上叫它為UI線程)。

因此,我們需要——那些負責讓頁面更好看、更好用的腳本應該立即加載,而那些可以待會兒再加載的腳本稍後再加載。

一、腳本延遲執行

現在越來越流行把腳本放在頁面

標籤的尾部。這樣,一方面使用者可以更快看到頁面,另一方面腳本可以直接操作已經載入完成的dom元素。對於大多數腳本而言,這次「搬家」是個巨大的進步。頁面模型如下—


複製程式碼 程式碼如下:




   
   


   
   


這確實大大加快了頁面的渲染時間,但是注意一點,這可能讓使用者有機會在載入bodyScript之前與頁面互動。源自於瀏覽器在載入完整個文件之前無法載入這些腳本,這對那些透過慢速連線傳送的大型文件來說會是一大瓶頸。

理想情況下,腳本的載入應該與文件的載入同時進行,並且不影響DOM的渲染。這樣,一旦文件就緒就可以運行腳本,因為已經按照<script>標籤的順序載入了對應腳本。 </script>

我們使用defer便能夠完成這樣的需求,即--


複製程式碼 程式碼如下:



新增defer屬性相當於告訴瀏覽器:請馬上開始載入這個腳本吧,但是,請等到文件就緒且先前所有具有defer屬性的腳本都結束運行之後再執行它。

這樣,在head標籤裡放入延遲腳本,技能帶來腳本置於body標籤時的所有好處,又能讓大文檔的載入速度大幅提升。此時的頁面模式是-


複製程式碼 程式碼如下:




   
   
   


   


但是並非所有的瀏覽器都支援defer(對於某些modern瀏覽器,如果聲明defer,其內部腳本將不會執行document.write及DOM渲染操作。IE4 皆支援defer屬性)。這意味著,如果您想確保自己的延遲腳本能在文件載入後運行,就必須將所有延遲腳本的程式碼都封裝在諸如jQuery之$(document).ready之類的結構中。這是值得的,因為差不多97%的訪客都能享受到並行加載的好處,同時另外3%的訪客仍然能使用功能完整的JavaScript。

二、腳本的完全並行化

讓腳本的載入及執行再快一步,我不想等到defer腳本一個接著一個運行(defer讓我們想到一種靜靜等待文檔加載的有序排隊場景),更不想等到文檔就緒之後才運行這些腳本,我想要盡快加載並且盡快運行這些腳本。這裡也就想到了HTML5的async屬性,但要注意,它是一種混亂的無政府狀態。

例如,我們加載兩個完全不相干的第三方腳本,頁面沒有它們也運行得很好,而且也不在乎它們誰先運行誰後運行。因此,對這些第三方腳本使用async屬性,相當於一分錢沒花就提升了它們的運行速度。

async屬性是HTML5新增的。作用和defer類似,即允許在下載腳本的同時進行DOM的渲染。但它將在下載後儘快執行(即JS引擎空閒了立刻執行),不能保證腳本會按順序執行。它們將在onload 事件之前完成。

Firefox 3.6、Opera 10.5、IE 9 和 最新的Chrome 和 Safari 都支援 async 屬性。可以同時使用 async 和 defer,這樣IE 4之後的所有 IE 都支援異步加載,但是要注意,async會覆蓋掉defer。

那麼此時的頁面模型如下-

複製程式碼 程式碼如下:




   
   
   


   
   
   


要注意這裡的執行順序——各個腳本檔案加載,接著執行headScript.js,緊接著在DOM渲染的同時會在後台加載defferedScript.js。接著在DOM渲染結束時將執行defferedScript.js和那兩個非同步腳本,要注意對於支援async屬性的瀏覽器而言,這兩個腳本將做無序運行。

三、可程式的腳本載入

儘管上面兩個腳本屬性的功能非常吸引人,但是由於相容性的問題,應用並不是很廣泛。故此,我們更多地使用腳本載入其他腳本。例如,我們只想給那些滿足一定條件的使用者載入某個腳本,也就是經常提到的「懶加載」。

在瀏覽器API層面,有兩種合理的方法來抓取並執行伺服器腳本-

1> 產生ajax請求並用eval函數處理回應

2> 插入DOM<script>標籤</script>

後一種方式比較好,因為瀏覽器會替我們操心生成HTTP請求這樣的事。再者,eval也有一些實際問題:洩漏作用域,調試搞得一團糟,而且還可能降低效能。因此,想要載入名為feture.js的腳本,我們應該使用類似下面的程式碼:


複製程式碼 程式碼如下:

var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.src = 'feature.js';
head.appendChild(script);

當然,我們要處理回呼監聽,HTML5規格定義了一個可以綁定回呼的onload屬性。


複製程式碼 程式碼如下:

script.onload = function() {
    console.log('script loaded ...');
}


不過,IE8及較舊的版本並不支援onload,它們支援的是onreadystatechange。而且,對於錯誤處理仍然千奇百怪。在這裡,可以多參考一些流行的校本載入函式庫,如labjs、yepnope、requirejs等。

如下,自己封裝了一個簡易loadjs檔案-


複製程式碼 程式碼如下:

var loadJS = function(url,callback){
    var head = document.getElementsByTagName('head')[0];
    var script = document.createElement('script');
    script.src = url;
    script.type = "text/javascript";
    head.appendChild( script);

    // script 標籤,IE下有onreadystatechange事件, w3c標準有onload事件
    // IE9 也支援 W3C標準的onload
    var ua = navigator.userAgent,
        ua_version;
    // IE6/7/8
    if (/MSIE ([^;] )/.test(ua)) {
        ua_version = parseFloat(RegExp["$1"], 10);
        if (ua_version             script.onreadystatechange = function(){
                if (this.readyState == "loaded" ){
                   則為 callback();
                }
            }
        } else {
            script.onload = function(){
               則為 callback();
            };
        }
    } else {
        script.onload = function(){
            callback();
        };
    }
};

document.write を使用したスクリプトの非同期読み込みについてはここでは説明しません。ブラウザー間の違いが非常にわかりにくいため、これを行う人はほとんどいません。

Image オブジェクトを使用して js ファイルを非同期的にプリロードする場合、内部の js コードは実行されないことに注意してください。

最後に、requirejs の非同期読み込みスクリプトについて話しましょう。

requirejs は、ターゲット スクリプトが順番に実行されることを保証するものではなく、実行順序がそれぞれの依存関係要件を満たすことができることのみを保証します。これにより、すべてのスクリプトができるだけ早く並行してロードされ、依存関係トポロジに従って順序正しく実行されるようになります。

4. 概要

OK、この時点で、非同期ロード スクリプトの記述は終了です。ここで最適化シーケンスについてもう一度詳しく説明します—

1> 従来の方法では、スクリプト タグを使用して HTML ドキュメントに直接埋め込みます。

という 2 つの状況があります。

a> head タグに埋め込みます。これにより、ドキュメント コンテンツ内の他の静的リソース ファイルの並列読み込みには影響しません。影響するのは、ドキュメント コンテンツのレンダリング、つまり DOM レンダリングです。この時点ではブロックされており、白い画面が表示されます。

b> body タグの下部に埋め込む - 白画面現象を回避するために、DOM レンダリングを優先してスクリプトを実行しましたが、問題が再発しました。まず最初の問題について説明します。DOM ドキュメントのコンテンツが比較的大きい場合、インタラクティブ イベントのバインドに遅延が発生し、エクスペリエンスが低下します。もちろん、必要に応じて重要なスクリプトを最初に実行させる必要があります。 2 番目の問題について話しましょう。スクリプト ファイルはボディの下部にあるため、これらのスクリプトの読み込みはヘッドのスクリプトに比べて遅れます。したがって、ボディの底面に関しては、最適化の終点ではありません。

c> defer 属性を追加します。スクリプトをできるだけ早く並行してロードしたいので、これらのスクリプトをヘッドに置きます。スクリプトはドキュメントの読み込みと同時に読み込まれる必要があり、DOM のレンダリングに影響を与えるべきではありません。こうすることで、ドキュメントの準備ができたらスクリプトを実行できます。したがって、defer のような属性があります。ただし、defer 属性をサポートしていないブラウザの場合は、jQuery などのコードを $(document).ready にカプセル化する必要があります。 defer 属性を持つすべてのスクリプトは出現順に順次実行されるため、厳密に同期されることに注意してください。

2> 前のポイントはすべて、スクリプトの同期実行に関するものです (これらのスクリプトの読み込みプロセスは並行して行われます。唯一の違いは、誰が最初にリクエストをトリガーし、誰が後でリクエストをトリガーするかです)。もちろん、ある時点で実行できるのは 1 つの js ファイルだけであることはわかっています。ここでの「並列」とは、js エンジンが有効である限り、最初にそれをロードした人がすぐに実行することを意味します。この時点ではアイドル状態です。ここでの最適化は 2 つのタイプに分けられます—

a> async 属性を追加すると、前述の最適化ポイントを確実に達成できますが、これには大きな制限があり、最も適切な例は、複数のサードパーティ スクリプトを導入することです。 deffer属性との組み合わせもありますが、これが本当に面倒です。もちろん、互換性の問題もあります。上記の 3 つの問題により、その用途は限定されます。 async を使用する場合は、依存関係に十分な注意を払ってください。

b> スクリプト読み込みスクリプト - 明らかに、「スクリプトの並列実行」の目的を達成するために使用します。同時に、スクリプトの依存関係の問題を制御するのにも便利なので、requirejs での js の非同期読み込みにインテリジェントな読み込み管理を使用します。

はい、ここに書きましょう。

ここでは、非同期読み込みスクリプトについてのみ説明します。もう 1 つのコンテンツがあります。これは、スタイル ファイルまたはその他の静的リソースの非同期読み込みです。つづく…

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
Python vs. JavaScript:開發人員的比較分析Python vs. JavaScript:開發人員的比較分析May 09, 2025 am 12:22 AM

Python和JavaScript的主要區別在於類型系統和應用場景。 1.Python使用動態類型,適合科學計算和數據分析。 2.JavaScript採用弱類型,廣泛用於前端和全棧開發。兩者在異步編程和性能優化上各有優勢,選擇時應根據項目需求決定。

Python vs. JavaScript:選擇合適的工具Python vs. JavaScript:選擇合適的工具May 08, 2025 am 12:10 AM

選擇Python還是JavaScript取決於項目類型:1)數據科學和自動化任務選擇Python;2)前端和全棧開發選擇JavaScript。 Python因其在數據處理和自動化方面的強大庫而備受青睞,而JavaScript則因其在網頁交互和全棧開發中的優勢而不可或缺。

Python和JavaScript:了解每個的優勢Python和JavaScript:了解每個的優勢May 06, 2025 am 12:15 AM

Python和JavaScript各有優勢,選擇取決於項目需求和個人偏好。 1.Python易學,語法簡潔,適用於數據科學和後端開發,但執行速度較慢。 2.JavaScript在前端開發中無處不在,異步編程能力強,Node.js使其適用於全棧開發,但語法可能複雜且易出錯。

JavaScript的核心:它是在C還是C上構建的?JavaScript的核心:它是在C還是C上構建的?May 05, 2025 am 12:07 AM

javascriptisnotbuiltoncorc; sanInterpretedlanguagethatrunsonenginesoftenwritteninc.1)JavascriptwasdesignedAsignedAsalightWeight,drackendedlanguageforwebbrowsers.2)Enginesevolvedfromsimpleterterpretpretpretpretpreterterpretpretpretpretpretpretpretpretpretcompilerers,典型地,替代品。

JavaScript應用程序:從前端到後端JavaScript應用程序:從前端到後端May 04, 2025 am 12:12 AM

JavaScript可用於前端和後端開發。前端通過DOM操作增強用戶體驗,後端通過Node.js處理服務器任務。 1.前端示例:改變網頁文本內容。 2.後端示例:創建Node.js服務器。

Python vs. JavaScript:您應該學到哪種語言?Python vs. JavaScript:您應該學到哪種語言?May 03, 2025 am 12:10 AM

選擇Python還是JavaScript應基於職業發展、學習曲線和生態系統:1)職業發展:Python適合數據科學和後端開發,JavaScript適合前端和全棧開發。 2)學習曲線:Python語法簡潔,適合初學者;JavaScript語法靈活。 3)生態系統:Python有豐富的科學計算庫,JavaScript有強大的前端框架。

JavaScript框架:為現代網絡開發提供動力JavaScript框架:為現代網絡開發提供動力May 02, 2025 am 12:04 AM

JavaScript框架的強大之處在於簡化開發、提升用戶體驗和應用性能。選擇框架時應考慮:1.項目規模和復雜度,2.團隊經驗,3.生態系統和社區支持。

JavaScript,C和瀏覽器之間的關係JavaScript,C和瀏覽器之間的關係May 01, 2025 am 12:06 AM

引言我知道你可能會覺得奇怪,JavaScript、C 和瀏覽器之間到底有什麼關係?它們之間看似毫無關聯,但實際上,它們在現代網絡開發中扮演著非常重要的角色。今天我們就來深入探討一下這三者之間的緊密聯繫。通過這篇文章,你將了解到JavaScript如何在瀏覽器中運行,C 在瀏覽器引擎中的作用,以及它們如何共同推動網頁的渲染和交互。 JavaScript與瀏覽器的關係我們都知道,JavaScript是前端開發的核心語言,它直接在瀏覽器中運行,讓網頁變得生動有趣。你是否曾經想過,為什麼JavaScr

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!