1. 程式人生 > 其它 >讓你輕鬆看懂defer和async

讓你輕鬆看懂defer和async

defer和async產生的原因

HTML 網頁中,瀏覽器通過<script>標籤載入 JavaScript 指令碼。
<!-- 頁面內嵌的指令碼 -->
<script type="application/javascript">
  // module code
</script>

<!-- 外部指令碼 -->
<script type="application/javascript" src="path/to/myModule.js">
</script>

由於瀏覽器指令碼的預設語言是 JavaScript。
因此type="application/javascript"是可以省略。
預設情況下,瀏覽器是同步載入 JavaScript 指令碼.
就是說渲染引擎遇到<script>標籤就會停下來,等到執行完指令碼,再繼續向下渲染。
如果是外部指令碼,還必須加入指令碼下載的時間。

如果指令碼體積很大,下載和執行的時間就會很長。
因此造成瀏覽器堵塞,使用者會感覺到瀏覽器“卡死”,使用者體驗不好
所以瀏覽器允許指令碼非同步載入,下面就是兩種非同步載入的語法。

<script src="path/to/myModule.js" defer></script>
<script src="path/to/myModule.js" async></script>

defer和async的簡單介紹

<script>標籤上有defer或async屬性,指令碼就會非同步載入。
渲染引擎遇到這一行命令,就會開始下載外部指令碼.
但不會等它下載和執行,而是直接執行後面的命令。

defer與async的區別是[面試題]

defer要等到整個頁面在記憶體中正常渲染結束(DOM 結構完全生成,以及其他指令碼執行完成),才會執行;
async一旦下載完,渲染引擎就會中斷渲染,執行這個指令碼以後,再繼續渲染。
一句話,defer是“渲染完再執行”,async是“下載完就執行”。
另外,如果有多個defer指令碼,會按照它們在頁面出現的順序載入,
而多個async指令碼是不能保證載入順序的。

ES6中script標籤module的作用

瀏覽器對於帶有type="module"的<script>,都是非同步載入。
不會造成堵塞瀏覽器的。
即等到整個頁面渲染完,再執行模組指令碼,
等同於打開了<script>標籤的defer屬性。

用程式碼來描述
<script type="module" src="./foo.js"></script>
<!-- 等同於 -->
<script type="module" src="./foo.js" defer></script>


如果網頁有多個<script type="module">,它們會按照在頁面出現的順序依次執行。
<script>標籤的async屬性也可以開啟,這時只要載入完成,
渲染引擎就會中斷渲染立即執行。執行完成後,再恢復渲染。
<script type="module" src="./foo.js" async></script>
一旦使用了async屬性,
<script type="module">就不會按照在頁面出現的順序執行,
而是隻要該模組載入完成,就執行該模組。