JavaScript非同步載入淺析_javascript技巧
前言
關於JavaScript腳本載入的問題,相信大家碰到很多。主要在幾個點-
1> 同步腳本與非同步腳本帶來的檔案載入、檔案依賴及執行順序問題
2> 同步腳本與非同步腳本帶來的效能最佳化問題
深入理解腳本載入相關的方方面面問題,不僅利於解決實際問題,更有利於對效能最佳化的掌握並執行。
先看隨便一個script標籤程式碼——
如果放在

其中,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 つのコンテンツがあります。これは、スタイル ファイルまたはその他の静的リソースの非同期読み込みです。つづく…

熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

標題:解決jQuery.val()不起作用的方法及程式碼範例在前端開發中,常會使用到jQuery來操作頁面元素。其中,取得或設定表單元素的值是常見的操作之一。通常,我們會使用jQuery的.val()方法來實作表單元素值的運算。然而,有時會遇到jQuery.val()不起作用的情況,這可能會導致一些問題。本文將介紹如何有效應對jQuery.val(

雖然HTML 本身無法讀取文件,但可以透過以下方法實作文件讀取:使用JavaScript(XMLHttpRequest、fetch());使用伺服器端語言(PHP、Node.js);使用第三方函式庫(jQuery.get() 、axios、fs-extra)。

委託是一種類型安全的參考類型,用於在物件之間傳遞方法指針,解決非同步程式設計和事件處理問題:非同步程式設計:委託允許在不同執行緒或進程中執行方法,提高應用程式回應能力。事件處理:委託簡化了事件處理,允許建立和處理事件,例如點擊或滑鼠移動。

前端開發者必備:掌握這些最佳化模式,讓網站飛起來!隨著網路的快速發展,網站已成為企業宣傳和交流的重要管道之一。一個效能優良、載入迅速的網站不僅可以提升使用者體驗,還可以吸引更多的訪客。身為前端開發者,掌握一些最佳化模式是不可或缺的。本文將介紹一些常用的前端優化技術,幫助開發者更好地優化網站。壓縮檔案在網站開發中,經常使用的檔案類型包括HTML、CSS和J

如何在WordPress中實現頁面不跳轉設定?在網站開發中,有時我們希望在WordPress中實現頁面不跳轉的設置,即在某些操作的時候,頁面內容可以更新但不刷新整個頁面。這樣可以提升使用者體驗,讓網站更加流暢。接下來,我們將分享如何在WordPress中實作頁面不跳轉設定的方法,並提供具體的程式碼範例。首先,我們可以使用Ajax來實現頁面不跳轉的功能。 Ajax

PHP搜尋功能一直是網站開發中非常重要的一環,因為使用者往往會透過搜尋框來尋找所需資訊。然而,不少網站在實現搜尋功能時存在效率低、搜尋結果不準確等問題。為了幫助大家優化PHP搜尋功能,本文將分享一些技巧,並提供具體的程式碼範例。 1.使用全文搜尋引擎傳統的SQL資料庫在處理大量文字內容時效率較低,因此建議使用全文搜尋引擎,如Elasticsearch、Solr等

若要在 HTML 中引入外部 JS 文件,請使用 <script> 標籤並指定要載入的文件的 URL。也可以指定 type、defer 或 async 屬性來控制載入和執行方式。通常,<script> 標籤應放置在 <body> 部分的底部,以避免阻塞頁面渲染。

網站效能優化大揭密:掌握這些方式,讓你的網站飛起來!隨著網路的快速發展,網站已成為企業宣傳、產品展示和交流互動的重要管道。然而,當使用者造訪網站時,如果載入速度過慢、回應時間過長,使用者體驗將會大打折扣,甚至可能直接導致使用者離開。因此,網站效能優化變得越來越重要。那麼,什麼是網站效能優化呢?簡單來說,網站效能優化是透過一系列的方式和技術手段,提升網站的載入速
