close

script中defer跟async是什麼?

在HTML5以前,script標籤沒有這兩個屬性,而瀏覽器單純的依照順序解析(parsing)並執行,HTML5之後,我們可以在script標籤定義他的行為,包括網路請求是否同步,執行時機等等。
給直接想知道答案的:
— async 會非同步去請求外部腳本 回應後停止解析執行腳本內容
— defer 也會非同步請求外部腳本 但是等待瀏覽器解析完才執行 (而且早於DOMContentLoaded 參考MDN)

 

Image for post


source — https://html.spec.whatwg.org/multipage/scripting.html
想明白一件事情,應該沿著歷史脈絡去探討這功能 — 誕生的原因與其脈絡。
所以我們先來討論一下最legacy,什麼也不加的case吧。
什麼都不加的狀況中,瀏覽器一旦解析到<script src=”example.com”>會依照以下操作:
停止解析
對src發起請求
等待
執行回應腳本 或是 請求失敗Exception
繼續向下解析
在以上一系列的操作中,可以知道1–5之間會有一些網路延遲,會導致整個瀏覽器解析卡死,無法繼續渲染。
Image for post
當你的使用者等了一段時間畫面還是白的…於是按下F12並打下history.back()時
但在當時,少數能做的只有選擇優秀的CDN,或是將script放在body閉合前的位置。
我們可以從以上的分析中知道這種問題多煩,而且解決方案多麼直觀,但在JavaScript的世界其實挺不直觀的,網路請求會不應該把其他無關的操作卡死。
於是我們的主角就出現了 — async & defer,這兩者都很棒,就像當年的AJAX崛起一樣,我們把請求射出去,繼續往下做其他事情,等到請求回來,再決定是否執行或是解析完在執行。
以下來一個說文解字吧
Image for post
Photo by Kaleidico on Unsplash
async —其實是asynchronous(非同步)的縮寫,非同步的發起請求,並且腳本回來之後,停止解析執行腳本,執行後恢復解析。
(用JS的非同步事件去想就挺直觀的)
async操作沒有辦法確保DOM都已經全部渲染
操作DOM可能等於找死,會QQ饅頭等著吃exception
所以這種async你比較常會在google analytics上看到,而非UI類庫。
請求回來的執行是會停止browser parsing喔
defer —其實是deferred(延遲)的縮寫,非同步的把請求射出去,然後再確保DOM全部都解析完畢之後執行,在DOMContentLoaded之前。
(直接射後不理,好球啦。)
腳本執行時,可以確保DOM已經完整渲染
在DOMContentLoaded前先去執行
反過來說,如果我們要有非同步的好處,又想要確保DOM已經被渲染完,我們就簡單的告訴瀏覽器,我們想要延遲(deffered)一波,這樣就可啦,這樣放哪理論上都不會出事了。
以上討論的屬性在沒有src屬性的狀況下(比如行內腳本),將失去作用。

 

文章轉載 https://medium.com/@realdennis/html-script-%E4%B8%ADdefer%E8%B7%9Fasync%E6%98%AF%E4%BB%80%E9%BA%BC-1166ee88d18
 

arrow
arrow

    Johnson峰 發表在 痞客邦 留言(0) 人氣()