目錄
實作js非同步載入
总结
首頁 web前端 js教程 幾個JavaScript異步加載相關問題

幾個JavaScript異步加載相關問題

Feb 22, 2018 am 09:06 AM
javascript js 相關

預設的js是同步載入的,這裡的“載入”可以理解成是解析、執行,而不是“下載”,在最新版本的瀏覽器中,瀏覽器對於程式碼請求的資源都是瀑布式的加載,而不是阻塞式的,但是js的執行總是阻塞的。這會引起什麼問題呢?如果我的index頁面要載入一些js,但是其中的某個請求遲遲得不到回應,於是阻塞了後面的js程式碼的執行(同步載入),同時頁面渲染也不能繼續(如果js引入是在head標籤後)。


<script type="text/javascript" src=&#39;http://china-addthis.googlecode.com/svn/trunk/addthis.js&#39;></script>
<script type="text/javascript" src=&#39;http://libs.baidu.com/jquery/2.0.0/jquery.min.js&#39;></script>
this is a test
登入後複製

例如上面的這段程式碼,儲存為index.html文件,頁面的主體是一個簡單的字串,但是程式碼執行後頁面遲遲都是空白,為何?因為請求的js遲遲無法載入(可能由於Google被牆等原因),於是阻塞了後面的程式碼的執行,頁面得不到渲染。可能你會提議,把js程式碼放到前不就能先渲染頁面了!好方法,我們嘗試將js放後面:


this is a test
<script type="text/javascript" src=&#39;http://china-addthis.googlecode.com/svn/trunk/addthis.js&#39;></script>
<script type="text/javascript" src=&#39;http://libs.baidu.com/jquery/2.0.0/jquery.min.js&#39;></script>
登入後複製

頁面瞬間被渲染,「this is a test」也很快出現在前台,世界似乎平靜了,可是:


this is a test
<script type="text/javascript" src=&#39;http://china-addthis.googlecode.com/svn/trunk/addthis.js&#39;></script>
<script type="text/javascript" src=&#39;http://libs.baidu.com/jquery/2.0.0/jquery.min.js&#39;></script>
登入後複製

在前面程式碼的基礎上簡單加了一段程式碼,但是"hello world"遲遲無法在控制台輸出,顯然前面的js請求阻塞了後面程式碼的載入,我們恍然大悟,改變js的載入位置只能改變頁面的渲染,然而對於js的載入並沒有什麼卵用,js還是會阻塞。

實作js非同步載入

我們的要求似乎很簡單,能在頁面載入的同時,在控制台輸出字串即可,再講的通俗一點,就是在請求第一段谷歌提供的js的同時,繼續執行下面的js,也就是實作js的非同步載入。

最常見的做法是動態產生script標籤:


<body>
 this is a test
 <script type="text/javascript">
  ~function() {
   var s = document.createElement(&#39;script&#39;);
   s.src = &#39;http://china-addthis.googlecode.com/svn/trunk/addthis.js&#39;;
   document.body.appendChild(s);
  }();
 </script>
 <script type="text/javascript" src=&#39;http://libs.baidu.com/jquery/2.0.0/jquery.min.js&#39;></script>
 <script type="text/javascript">
  console.log(&#39;hello world&#39;);
 </script>
</body>
登入後複製

但還是有點問題,這種載入方式在載入執行完之前會阻止onload 事件的觸發,而現在很多頁面的程式碼在onload 時還要執行額外的渲染工作等,所以還是會阻塞部分頁面的初始化處理:


<body>
 this is a test
 <script type="text/javascript">
  ~function() {
   // function async_load() {
    var s = document.createElement(&#39;script&#39;);
    s.src = &#39;http://china-addthis.googlecode.com/svn/trunk/addthis.js&#39;;
    document.body.appendChild(s);
   // }
   // window.addEventListener(&#39;load&#39;, async_load, false);
  }();

  window.onload = function() {
   var txt = document.createTextNode(&#39; hello world&#39;);
   document.body.appendChild(txt);
  };
 </script>
 <script type="text/javascript" src=&#39;http://libs.baidu.com/jquery/2.0.0/jquery.min.js&#39;></script>
</body>
登入後複製

例如上面的程式碼不能很好地渲染”hello world”,我們只需將註解去掉就可以了,讓Google提供的js在onload 時才開始非同步載入。這樣就解決了阻塞 onload 事件觸發的問題。

補充DOMContentLoaded 與 OnLoad 事件 DOMContentLoaded : 頁面(document)已經解析完成,頁面中的dom元素已經可用。但是頁面中引用的圖片、subframe可能還沒載入完。 OnLoad:頁面的所有資源都加載完畢(包括圖片)。瀏覽器的載入進度在這時才停止。這兩個時間點將頁面載入的timeline分成了三個階段。

以上似乎能較好解決這個問題,但html5提供了更簡單的方法,async屬性!


this is a test
<script type="text/javascript" src=&#39;http://china-addthis.googlecode.com/svn/trunk/addthis.js&#39; async=&#39;async&#39;></script>
<script type="text/javascript" src=&#39;http://libs.baidu.com/jquery/2.0.0/jquery.min.js&#39;></script>
<script type="text/javascript">
 console.log(&#39;hello world&#39;);
</script>
登入後複製

async是html5的新屬性,async 屬性規定一旦腳本可用,則會非同步執行(一旦下載完成就會立刻執行)。

要注意的是async 屬性只適用於外部腳本(只有在使用src 屬性時)

defer屬性常常和async一起提起:


this is a test
<script type="text/javascript" src=&#39;http://china-addthis.googlecode.com/svn/trunk/addthis.js&#39; defer=&#39;defer&#39;></script>
<script type="text/javascript" src=&#39;http://libs.baidu.com/jquery/2.0.0/jquery.min.js&#39;></script>
<script type="text/javascript">
 console.log(&#39;hello world&#39;);
</script>
登入後複製

似乎實現效果差不多,但真的一樣嗎?我們來看看defer屬性的定義。

以前的defer只支援ie的hack,現在html5的出現開始全面支援defer。 defer 屬性規定當頁面已完成載入後,才會執行腳本。 defer 屬性僅適用於外部腳本(只有在使用 src 屬性時)。 ps:ie支持的defer似乎並非如此,因為對ie無感,不深究,有興趣的可以去查閱相關資料。

既然async和defer常常一起出現,那麼辨識一下吧!

如果沒有async和defer屬性(賦值為true,下同),那麼瀏覽器會立即執行目前的js腳本,阻塞後面的腳本;如果有async屬性,載入和渲染後續文件元素的過程將會和目前js的載入與執行並行進行(非同步);如果有defer屬性,那麼載入後續文件元素的過程將會和script.js 的載入並行進行(非同步),但是script.js 的執行要在所有元素( DOM)解析完成之後,DOMContentLoaded 事件觸發前完成。

來看一張網路上盜的圖:

藍色線代表網路讀取,紅色線代表執行時間,這兩個都是針對腳本的;綠線代表HTML 解析。

此圖告訴我們以下幾個要點(摘自defer和async的區別):

  1. #defer 和async 在網路讀取(下載)這塊兒是一樣的,都是非同步的(相較於HTML 解析)

  2. 它倆的差別在於腳本下載完之後何時執行,顯然defer 是最接近我們對於應用程式腳本載入和執行的要求的

  3. 关于 defer,此图未尽之处在于它是按照加载顺序执行脚本的,这一点要善加利用

  4. async 则是一个乱序执行的主,反正对它来说脚本的加载和执行是紧紧挨着的,所以不管你声明的顺序如何,只要它加载完了就会立刻执行

  5. 仔细想想,async 对于应用脚本的用处不大,因为它完全不考虑依赖(哪怕是最低级的顺序执行),不过它对于那些可以不依赖任何脚本或不被任何脚本依赖的脚本来说却是非常合适的,最典型的例子:Google Analytics

但是在我看来(以下个人理解,如有出入还望指出),defer在异步加载上的应用并不会比async广。async的英文解释是异步,该属性作用在脚本上,使得脚本加载(下载)完后随即开始执行,和动态插入script标签作用类似(async只支持h5,后者能兼容浏览器);而defer的英文解释是延迟,作用也和字面解释类似,延迟脚本的执行,使得dom元素加载完后才开始有序执行脚本,因为有序,所以会带来另一个问题:


this is a test
<script type="text/javascript" src=&#39;http://china-addthis.googlecode.com/svn/trunk/addthis.js&#39; defer=&#39;defer&#39;></script>
<script type="text/javascript" src=&#39;http://libs.baidu.com/jquery/2.0.0/jquery.min.js&#39; defer=&#39;defer&#39;></script>
<script type="text/javascript" src=&#39;index.js&#39; defer=&#39;defer&#39;></script>
console.log(&#39;hello world&#39;);
登入後複製

如果执行这段代码,控制台的“hello world”也会迟迟得不到结果。所以我觉得还是async好用,如果要考虑依赖的话,可以选择requirejs、seajs等模块加载器。

总结

JavaScript的异步加载还有一些方式,比如:AJAX eval(使用AJAX得到脚本内容,然后通过eval(xmlhttp.responseText)来运行脚本)、iframe方式等。

相关推荐:

Angular结合zTree异步加载节点数据实例分享

JavaScript文件的同步和异步加载的实现代码

使用DataTable插件实现异步加载数据详解


以上是幾個JavaScript異步加載相關問題的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱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

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

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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

如何使用WebSocket和JavaScript實現線上語音辨識系統 如何使用WebSocket和JavaScript實現線上語音辨識系統 Dec 17, 2023 pm 02:54 PM

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

建議:優秀JS開源人臉偵測辨識項目 建議:優秀JS開源人臉偵測辨識項目 Apr 03, 2024 am 11:55 AM

人臉偵測辨識技術已經是一個比較成熟且應用廣泛的技術。而目前最廣泛的網路應用語言非JS莫屬,在Web前端實現人臉偵測辨識相比後端的人臉辨識有優勢也有弱勢。優點包括減少網路互動、即時識別,大大縮短了使用者等待時間,提高了使用者體驗;弱勢是:受到模型大小限制,其中準確率也有限。如何在web端使用js實現人臉偵測呢?為了實現Web端人臉識別,需要熟悉相關的程式語言和技術,如JavaScript、HTML、CSS、WebRTC等。同時也需要掌握相關的電腦視覺和人工智慧技術。值得注意的是,由於Web端的計

WebSocket與JavaScript:實現即時監控系統的關鍵技術 WebSocket與JavaScript:實現即時監控系統的關鍵技術 Dec 17, 2023 pm 05:30 PM

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

股票分析必備工具:學習PHP和JS繪製蠟燭圖的步驟 股票分析必備工具:學習PHP和JS繪製蠟燭圖的步驟 Dec 17, 2023 pm 06:55 PM

股票分析必備工具:學習PHP和JS繪製蠟燭圖的步驟,需要具體程式碼範例隨著網路和科技的快速發展,股票交易已成為許多投資者的重要途徑之一。而股票分析是投資人決策的重要一環,其中蠟燭圖被廣泛應用於技術分析。學習如何使用PHP和JS繪製蠟燭圖將為投資者提供更多直觀的信息,幫助他們更好地做出決策。蠟燭圖是一種以蠟燭形狀來展示股票價格的技術圖表。它展示了股票價格的

如何利用JavaScript和WebSocket實現即時線上點餐系統 如何利用JavaScript和WebSocket實現即時線上點餐系統 Dec 17, 2023 pm 12:09 PM

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統 如何使用WebSocket和JavaScript實現線上預約系統 Dec 17, 2023 am 09:39 AM

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript與WebSocket:打造高效率的即時天氣預報系統 JavaScript與WebSocket:打造高效率的即時天氣預報系統 Dec 17, 2023 pm 05:13 PM

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

PHP與JS開發技巧:掌握繪製股票蠟燭圖的方法 PHP與JS開發技巧:掌握繪製股票蠟燭圖的方法 Dec 18, 2023 pm 03:39 PM

隨著網路金融的快速發展,股票投資已經成為了越來越多人的選擇。而在股票交易中,蠟燭圖是常用的技術分析方法,它能夠顯示股票價格的變動趨勢,幫助投資人做出更精準的決策。本文將透過介紹PHP和JS的開發技巧,帶領讀者了解如何繪製股票蠟燭圖,並提供具體的程式碼範例。一、了解股票蠟燭圖在介紹如何繪製股票蠟燭圖之前,我們首先需要先了解什麼是蠟燭圖。蠟燭圖是由日本人

See all articles