JavaScript - 延遲 vs 異步

本文譯自 -> 傳送門
作者:Ire Aderinokun |
譯者:fishc.com

JavaScript 被認(rèn)為是 “解析器阻塞資源”墨状。這意味著 HTML 文檔自身的解析將被 JavaScript 阻塞。即當(dāng)解析器到達(dá) <script> 標(biāo)簽時(shí)柑爸,無論是內(nèi)嵌還是引用外部代碼,解析器都會(huì)暫停 HTML 的解析盒音,轉(zhuǎn)而獲缺眵ⅰ(如果不是內(nèi)嵌)并執(zhí)行代碼。

這種行為邏輯可能會(huì)導(dǎo)致一些問題祥诽,比如當(dāng)我們?cè)陧撁嬷屑虞d多個(gè) JavaScript 文件時(shí)譬圣,無論實(shí)際上是否需要用到它們,瀏覽器都會(huì)將它們?nèi)枯d入原押,這樣一來胁镐,網(wǎng)頁的加載速度就受到了影響。

不過幸運(yùn)的是诸衔,script 元素?fù)碛袃蓚€(gè)屬性:async 和 defer盯漂,它們?cè)试S你控制代碼文件的獲取和執(zhí)行。

正常的執(zhí)行流程

在研究這兩個(gè)屬性之前笨农,我們先看看正常情況下代碼文件的執(zhí)行流程就缆。

在默認(rèn)情況下,如上所述谒亦,JavaScript 文件將中斷 HTML 文檔的解析竭宰,以便獲瓤战肌(如果不是內(nèi)嵌)并執(zhí)行代碼。

舉個(gè)例子切揭,下面代碼中 script 元素位于頁面中間的某個(gè)位置:

<html>
<head> ... </head>
<body>
    ...
    <script src="script.js">
    ....
</body>
</html>

當(dāng)文檔解析器遍歷頁面遇到 <script> 標(biāo)簽時(shí)狞甚,會(huì)發(fā)生下面這種情況:

如上,HTML 解析將被代碼的獲取和執(zhí)行所中斷廓旬,從而延長(zhǎng)了第一次繪制網(wǎng)頁所需的時(shí)間哼审。

async屬性

async 屬性用于告訴瀏覽器該代碼可以被異步執(zhí)行。

HTML 解析器在遇到該 <script> 標(biāo)簽的時(shí)候不需要停下來孕豹,HTML 文檔的解析和代碼的獲取是同時(shí)進(jìn)行的涩盾,直到外部文件獲取完成,才會(huì)暫停下來執(zhí)行代碼励背。

<script async src="script.js">

該屬性僅適用于引用外部代碼文件的情況春霍。

當(dāng)文檔解析器遍歷頁面遇到 <script> 標(biāo)簽時(shí),會(huì)發(fā)生下面這種情況:


defer 屬性

defer 屬性用于告訴瀏覽器只有再 HTML 文檔全部解析完成之后再支持代碼文件叶眉。

<script defer src="script.js">

類似于異步加載代碼(async)址儒,代碼文件的獲取和 HTML 文檔的解析是可以并行的。然而竟闪,代碼并不會(huì)再獲取完成后立即執(zhí)行离福,它會(huì)等到所有的 HTML 文檔解析完畢后再執(zhí)行杖狼。


應(yīng)該選擇異步炼蛤,延遲還是正常執(zhí)行代碼?

那么問題來了蝶涩,什么時(shí)候我們應(yīng)該使用異步理朋,時(shí)候使用延遲,什么時(shí)候又讓它正常執(zhí)行绿聘?

這視具體情況而定嗽上,但決定前請(qǐng)先考慮下面幾個(gè)問題:

  • script 元素放置的位置?
    只有當(dāng) script 元素沒有放在 HTML 的末尾時(shí)熄攘,異步和延遲執(zhí)行代碼才有意義兽愤。
    從 <html> 到 </html>,HTML 文檔按順序被解析挪圾。如果在關(guān)閉 </body> 標(biāo)簽之前放置了一個(gè)引用外部的 JavaScript 文件浅萧,那么使用異步或延遲加載代碼就顯得意義不大,因?yàn)榇藭r(shí)解析器已經(jīng)完成了絕大部分 HTML 文檔的解析工作哲思。

  • 代碼是否獨(dú)立洼畅?
    對(duì)于不依賴于其他文件或本身沒有任何依賴關(guān)系的代碼文件,async 屬性將會(huì)非常有用棚赔,因?yàn)槲覀儾⒉辉谝馑裁磿r(shí)候被執(zhí)行帝簇。這也是異步加載最常見的情況徘郭。

  • 代碼的執(zhí)行是否依賴于完全解析后的 DOM?
    在很多情況下丧肴,代碼文件包含需要與 DOM 進(jìn)行交互的功能残揉。
    或者,它可能依賴于頁面上包含的另一個(gè)文件芋浮。
    在這些情況下冲甘,必須在代碼執(zhí)行之前先完全解析 DOM。
    通常途样,這樣的代碼文件將被放置到頁面的底部江醇,以確保 DOM 的所有內(nèi)容已經(jīng)被解析完畢。
    然而何暇,在出于任何原因需要將 script 元素放置在別處的情況下陶夜,可以使用 defer 屬性。

  • 是一個(gè)短小精悍的代碼裆站?
    最后条辟,如果代碼尺寸相對(duì)較小,自身執(zhí)行時(shí)間也很短宏胯,則將其定義為內(nèi)嵌代碼可能更加合適羽嫡。
    盡管內(nèi)嵌代碼會(huì)阻止 HTML 文檔的解析,但如果執(zhí)行代碼的時(shí)間很短肩袍,它應(yīng)該不是一個(gè)很大的干擾項(xiàng)杭棵。
    另外,如果它依賴于其他文件氛赐,則可能需要短時(shí)間的阻塞(加載并)魂爪。

現(xiàn)代瀏覽器引擎的支持程度

各家瀏覽器開始支持 async 屬性的版本號(hào):


各家瀏覽器開始支持 defer 屬性的版本號(hào):


值得注意的是,這些屬性的行為在不同的 JavaScript 引擎中可能略有不同艰管。

例如滓侍,在 V8 中(Chromium),無論其屬性如何牲芋,都將嘗試在用于代碼執(zhí)行的單獨(dú)專用線程上解析所有代碼撩笆。在這種情況下,JavaScript 代碼文件的 “解析器阻塞” 影響應(yīng)該是控制在最小的缸浦。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末夕冲,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子餐济,更是在濱河造成了極大的恐慌耘擂,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件絮姆,死亡現(xiàn)場(chǎng)離奇詭異醉冤,居然都是意外死亡秩霍,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門蚁阳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來铃绒,“玉大人,你說我怎么就攤上這事螺捐〉咝” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵定血,是天一觀的道長(zhǎng)赔癌。 經(jīng)常有香客問我,道長(zhǎng)澜沟,這世上最難降的妖魔是什么灾票? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮茫虽,結(jié)果婚禮上刊苍,老公的妹妹穿的比我還像新娘。我一直安慰自己濒析,他們只是感情好正什,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著号杏,像睡著了一般婴氮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上馒索,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天莹妒,我揣著相機(jī)與錄音,去河邊找鬼绰上。 笑死,一個(gè)胖子當(dāng)著我的面吹牛渠驼,可吹牛的內(nèi)容都是我干的蜈块。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼迷扇,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼百揭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蜓席,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤器一,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后厨内,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體祈秕,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡渺贤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了请毛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片志鞍。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖方仿,靈堂內(nèi)的尸體忽然破棺而出固棚,到底是詐尸還是另有隱情,我是刑警寧澤仙蚜,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布盒延,位于F島的核電站套利,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜叉趣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望郭计。 院中可真熱鬧涝登,春花似錦、人聲如沸氮双。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽戴差。三九已至送爸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間暖释,已是汗流浹背袭厂。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留球匕,地道東北人纹磺。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像亮曹,于是被迫代替她去往敵國(guó)和親橄杨。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5照卦? 答:HTML5是最新的HTML標(biāo)準(zhǔn)式矫。 注意:講述HT...
    kismetajun閱讀 27,447評(píng)論 1 45
  • 本文總結(jié)一下瀏覽器在 javascript 的加載方式。關(guān)鍵詞:異步加載(async loading)役耕,延遲加載(...
    4ea0af17fd67閱讀 1,057評(píng)論 0 2
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,090評(píng)論 1 32
  • 客戶端JavaScript web瀏覽器中的JavaScript 一. 客戶端JavaScript 1. docu...
    恰皮閱讀 542評(píng)論 0 0
  • 一采转、本周做了什么? 1瞬痘、身體健康: 面膜:2次故慈; 跑步3次板熊,共計(jì)14km;本周日均步行:7112步惯悠;冥想:2天邻邮; ...
    安塵lee閱讀 231評(píng)論 1 1