成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

學習 Async,Defer 和動態腳本,本文就夠了!

安全
當瀏覽器加載 HTML 時遇到 標簽,瀏覽器就不能繼續構建 DOM。它必須立刻執行此腳本。對于外部腳本 也是一樣的:瀏覽器必須等腳本下載完,并執行結束,之后才能繼續處理剩余的頁面。

[[357001]]

腳本:async,defer

現代的網站中,腳本往往比 HTML 更“重”:它們的大小通常更大,處理時間也更長。

當瀏覽器加載 HTML 時遇到 標簽,瀏覽器就不能繼續構建 DOM。它必須立刻執行此腳本。對于外部腳本 也是一樣的:瀏覽器必須等腳本下載完,并執行結束,之后才能繼續處理剩余的頁面。

這會導致兩個重要的問題:

  1. 腳本不能訪問到位于它們下面的 DOM 元素,因此,腳本無法給它們添加處理程序等。
  2. 如果頁面頂部有一個笨重的腳本,它會“阻塞頁面”。在該腳本下載并執行結束前,用戶都不能看到頁面內容:
  1. <p>...content before script...</p> 
  2.  
  3. <script src="https://javascript.info/article/script-async-defer/long.js?speed=1"></script> 
  4.  
  5. <!-- This isn't visible until the script loads --> 
  6. <p>...content after script...</p> 

這里有一些解決辦法。例如,我們可以把腳本放在頁面底部。此時,它可以訪問到它上面的元素,并且不會阻塞頁面顯示內容:

  1. <body> 
  2.   ...all content is above the script... 
  3.  
  4.   <script src="https://javascript.info/article/script-async-defer/long.js?speed=1"></script> 
  5. </body> 

但是這種解決方案遠非完美。例如,瀏覽器只有在下載了完整的 HTML 文檔之后才會注意到該腳本(并且可以開始下載它)。對于長的 HTML 文檔來說,這樣可能會造成明顯的延遲。

這對于使用高速連接的人來說,這不值一提,他們不會感受到這種延遲。但是這個世界上仍然有很多地區的人們所使用的網絡速度很慢,并且使用的是遠非完美的移動互聯網連接。

幸運的是,這里有兩個 <script> 特性(attribute)可以為我們解決這個問題:defer 和 async。

 defer

defer 特性告訴瀏覽器不要等待腳本。相反,瀏覽器將繼續處理 HTML,構建 DOM。腳本會“在后臺”下載,然后等 DOM 構建完成后,腳本才會執行。

 

這是與上面那個相同的示例,但是帶有 defer 特性:

  1. <p>...content before script...</p> 
  2.  
  3. <script defer src="https://javascript.info/article/script-async-defer/long.js?speed=1"></script> 
  4.  
  5. <!-- 立即可見 --> 
  6. <p>...content after script...</p> 

換句話說:

  • 具有 defer 特性的腳本不會阻塞頁面。
  • 具有 defer 特性的腳本總是要等到 DOM 解析完畢,但在 DOMContentLoaded 事件之前執行。

下面這個示例演示了上面所說的第二句話:

  1. <p>...content before scripts...</p> 
  2.  
  3. <script> 
  4.   document.addEventListener('DOMContentLoaded', () => alert("DOM ready after defer!")); 
  5. </script> 
  6.  
  7. <script defer src="https://javascript.info/article/script-async-defer/long.js?speed=1"></script> 
  8.  
  9. <p>...content after scripts...</p> 
  1. 頁面內容立即顯示。
  2. DOMContentLoaded 事件處理程序等待具有 defer 特性的腳本執行完成。它僅在腳本下載且執行結束后才會被觸發。

具有 defer 特性的腳本保持其相對順序,就像常規腳本一樣。

假設,我們有兩個具有 defer 特性的腳本:long.js 在前,small.js 在后。

  1. <script defer src="https://javascript.info/article/script-async-defer/long.js"></script> 
  2. <script defer src="https://javascript.info/article/script-async-defer/small.js"></script> 

瀏覽器掃描頁面尋找腳本,然后并行下載它們,以提高性能。因此,在上面的示例中,兩個腳本是并行下載的。small.js 可能會先下載完成。

……但是,defer 特性除了告訴瀏覽器“不要阻塞頁面”之外,還可以確保腳本執行的相對順序。因此,即使 small.js 先加載完成,它也需要等到 long.js 執行結束才會被執行。

當我們需要先加載 JavaScript 庫,然后再加載依賴于它的腳本時,這可能會很有用。

defer 特性僅適用于外部腳本

如果 <script> 腳本沒有 src,則會忽略 defer 特性。

async

 async 特性與 defer 有些類似。它也能夠讓腳本不阻塞頁面。但是,在行為上二者有著重要的區別。

async 特性意味著腳本是完全獨立的:

  • 瀏覽器不會因 async 腳本而阻塞(與 defer 類似)。
  • 其他腳本不會等待 async 腳本加載完成,同樣,async 腳本也不會等待其他腳本。
  • DOMContentLoaded 和異步腳本不會彼此等待:
    • DOMContentLoaded 可能會發生在異步腳本之前(如果異步腳本在頁面完成后才加載完成)
    • DOMContentLoaded 也可能發生在異步腳本之后(如果異步腳本很短,或者是從 HTTP 緩存中加載的)

換句話說,async 腳本會在后臺加載,并在加載就緒時運行。DOM 和其他腳本不會等待它們,它們也不會等待其它的東西。async 腳本就是一個會在加載完成時執行的完全獨立的腳本。就這么簡單,現在明白了吧?

下面是一個類似于我們在講 defer 時所看到的例子:long.js 和 small.js 兩個腳本,只是現在 defer 變成了 async。

它們不會等待對方。先加載完成的(可能是 small.js)—— 先執行:

  1. <p>...content before scripts...</p> 
  2.  
  3. <script> 
  4.   document.addEventListener('DOMContentLoaded', () => alert("DOM ready!")); 
  5. </script> 
  6.  
  7. <script async src="https://javascript.info/article/script-async-defer/long.js"></script> 
  8. <script async src="https://javascript.info/article/script-async-defer/small.js"></script> 
  9.  
  10. <p>...content after scripts...</p> 
  • 頁面內容立刻顯示出來:加載寫有 async 的腳本不會阻塞頁面渲染。
  • DOMContentLoaded 可能在 async 之前或之后觸發,不能保證誰先誰后。
  • 較小的腳本 small.js 排在第二位,但可能會比 long.js 這個長腳本先加載完成,所以 small.js 會先執行。雖然,可能是 long.js 先加載完成,如果它被緩存了的話,那么它就會先執行。換句話說,異步腳本以“加載優先”的順序執行。

當我們將獨立的第三方腳本集成到頁面時,此時采用異步加載方式是非常棒的:計數器,廣告等,因為它們不依賴于我們的腳本,我們的腳本也不應該等待它們:

  1. <!-- Google Analytics 腳本通常是這樣嵌入頁面的 --> 
  2. <script async src="https://google-analytics.com/analytics.js"></script> 

動態腳本

此外,還有一種向頁面添加腳本的重要的方式。

我們可以使用 JavaScript 動態地創建一個腳本,并將其附加(append)到文檔(document)中:

  1. let script = document.createElement('script'); 
  2. script.src = "/article/script-async-defer/long.js"
  3. document.body.append(script); // (*) 

當腳本被附加到文檔 (*) 時,腳本就會立即開始加載。

默認情況下,動態腳本的行為是“異步”的。

也就是說:

  • 它們不會等待任何東西,也沒有什么東西會等它們。
  • 先加載完成的腳本先執行(“加載優先”順序)。

如果我們顯式地設置了 script.async=false,則可以改變這個規則。然后腳本將按照腳本在文檔中的順序執行,就像 defer 那樣。

在下面這個例子中,loadScript(src) 函數添加了一個腳本,并將 async 設置為了 false。

因此,long.js 總是會先執行(因為它是先被添加到文檔的):

  1. function loadScript(src) { 
  2.   let script = document.createElement('script'); 
  3.   script.src = src; 
  4.   script.async = false
  5.   document.body.append(script); 
  6.  
  7. // long.js 先執行,因為代碼中設置了 async=false 
  8. loadScript("/article/script-async-defer/long.js"); 
  9. loadScript("/article/script-async-defer/small.js"); 

如果沒有 script.async=false,腳本則將以默認規則執行,即加載優先順序(small.js 大概會先執行)。

同樣,和 defer 一樣,如果我們要加載一個庫和一個依賴于它的腳本,那么順序就很重要。

總結

async 和 defer 有一個共同點:加載這樣的腳本都不會阻塞頁面的渲染。因此,用戶可以立即閱讀并了解頁面內容。

但是,它們之間也存在一些本質的區別:

順序 DOMContentLoaded
async 加載優先順序。腳本在文檔中的順序不重要 —— 先加載完成的先執行 不相關。可能在文檔加載完成前加載并執行完畢。如果腳本很小或者來自于緩存,同時文檔足夠長,就會發生這種情況。
defer 文檔順序(它們在文檔中的順序) 在文檔加載和解析完成之后(如果需要,則會等待),即在 DOMContentLoaded 之前執行。

在這種情況下,某些圖形組件可能尚未初始化完成。

因此,請記得添加一個“正在加載”的提示,并禁用尚不可用的按鈕。以讓用戶可以清楚地看到,他現在可以在頁面上做什么,以及還有什么是正在準備中的。

現代 JavaScript 教程:開源的現代 JavaScript 從入門到進階的優質教程。React 官方文檔推薦,與 MDN 并列的 JavaScript 學習教程[1]。

在線免費閱讀:https://zh.javascript.info

參考資料

[1]

React 官方文檔推薦,與 MDN 并列的 JavaScript 學習教程: https://zh-hans.reactjs.org/docs/getting-started.html#javascript-resources

本文轉載自微信公眾號「技術漫談」,可以通過以下二維碼關注。轉載本文請聯系技術漫談公眾號。

 

責任編輯:武曉燕 來源: 技術漫談
相關推薦

2020-02-24 19:28:23

Rust語言Web框架應用領域

2021-12-06 09:57:25

容器Linux信號

2022-08-09 15:38:55

Linux

2022-06-20 09:01:23

Git插件項目

2021-04-08 07:37:39

隊列數據結構算法

2020-09-18 16:37:59

數據可視化技術Python

2017-03-11 22:19:09

深度學習

2021-01-18 11:41:22

SQL數據庫編程語言

2018-07-06 15:25:50

程序員編程python

2025-02-14 08:53:24

2021-09-27 10:19:24

機器學習情緒分析工具AI人工智能

2022-03-13 09:31:43

MQ消息隊列ActiveMQ

2019-08-16 09:41:56

UDP協議TCP

2021-09-30 07:59:06

zookeeper一致性算法CAP

2021-06-07 06:25:35

畫流程圖開發技能

2015-11-02 09:49:04

Android屏幕適配官方指導

2021-10-13 16:54:22

IPv6網絡5G

2021-09-02 07:00:32

鑒權Web 應用Cookie-sess

2019-10-31 09:48:53

MySQL數據庫事務

2010-08-26 10:47:05

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 自拍偷拍欧美 | 九九热在线观看视频 | 中文字幕一区二区三区不卡在线 | 午夜视频一区二区 | 久久久区 | 亚洲一区电影 | 懂色av色香蕉一区二区蜜桃 | 欧美亚洲成人网 | 一区二区免费视频 | 色综合久 | 欧美乱操 | 欧美在线不卡 | 午夜精品久久久 | 久久久久国产精品免费免费搜索 | 久久成人一区 | 亚洲国产激情 | 久草久草久草 | 亚洲欧美日韩久久 | 欧美日韩不卡合集视频 | 综合久久久 | 日本一区二区三区四区 | 91视频在线 | 亚洲电影在线播放 | 99视频在线免费观看 | 免费v片在线观看 | 日韩中文在线 | www国产成人 | 国产在线一区二区三区 | 亚洲成av人片在线观看 | 久久久久久艹 | 在线成人 | 一区二区三区精品视频 | 性色网站| 鲁大师一区影视 | 91欧美| 久久人人网 | 亚洲 中文 欧美 日韩 在线观看 | 自拍偷拍第一页 | 黄a免费看 | 日韩午夜网站 | 国产精品久久久久久久久久久久 |