如何實現(xiàn)JS異步加載

去百度運維部面試時,問的問題是:
1.當(dāng)CSS執(zhí)行卡住時秩仆,DOM會不會繼續(xù)渲染码泛?如果是JS卡住呢?
2.有沒有用過<script>標簽的async屬性澄耍?

該總結(jié)看似和以上兩個問題不相關(guān)噪珊,實則回答了以上問題。

一齐莲、為什么要JS異步加載痢站?

因為同步加載存在問題!

JS在默認情況下是以同步模式(又稱阻塞模式)加載的选酗,這里“加載”的意思是“解釋阵难、執(zhí)行”。在最新版本的瀏覽器中芒填,瀏覽器對于代碼請求的資源都是瀑布式的加載呜叫,而不是阻塞式的,但是JS的執(zhí)行總是阻塞的氢烘。這會引起什么問題呢怀偷?如果在頁面中加載一些JS,但其中某個請求遲遲得不到響應(yīng)播玖,位于此JS后面的JS將無法執(zhí)行椎工,同時頁面渲染也不能繼續(xù),用戶看到的就是白屏(此時JS在<head>標簽之后引入)蜀踏。

<head>
       <meta charset="UTF-8">
       <title>test</title>
       <script type="text/javascript" src='http://china-addthis.googlecode.com/svn/trunk/addthis.js'></script>
       <script type="text/javascript" src='http://libs.baidu.com/jquery/2.0.0/jquery.min.js'></script>
</head>
<body>
   <p>我是小仙女</p>
</body>

這是一個簡單的html文件维蒙,頁面的主體是簡單地文本段落,但是代碼執(zhí)行后遲遲都是空白果覆。為什么呢颅痊?因為第一個請求的JS遲遲無法加載,于是阻塞了后面代碼的執(zhí)行局待,頁面得不到渲染斑响。
那該怎么辦呢菱属?你可能會想到一個方法,把JS代碼放到</body>標簽之前舰罚!好主意纽门!于是我們把JS放在HTML語句后面(這也是所提倡的頁面結(jié)構(gòu))。

<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body>
   <p>我是小仙女</p>
   <script type="text/javascript" src='http://china-addthis.googlecode.com/svn/trunk/addthis.js'></script>
   <script type="text/javascript" src='http://libs.baidu.com/jquery/2.0.0/jquery.min.js'></script>
</body>

頁面瞬間被渲染营罢,問題似乎解決了赏陵,可是...

<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body>
   <p>我是小仙女</p>
   <script type="text/javascript" src='http://china-addthis.googlecode.com/svn/trunk/addthis.js'></script>
   <script type="text/javascript" src='http://libs.baidu.com/jquery/2.0.0/jquery.min.js'></script>
   <script type="text/javascript">
      alert("hello world");
   </script>
</body>

我們在前面代碼的基礎(chǔ)上簡單加了一段代碼,但"hello world"遲遲無法被彈出饲漾,顯然是因為前面的JS請求阻塞了后面代碼的加載蝙搔。這時同步加載的問題依然存在:改變JS的加載位置只能改變頁面的渲染,JS還是會阻塞考传。

二吃型、如何實現(xiàn)JS異步加載?

異步加載即非阻塞加載僚楞,瀏覽器在加載JS的同時败玉,還會繼續(xù)進行后續(xù)頁面的處理。在本例中镜硕,我們想實現(xiàn)在請求第一段谷歌提供的JS的同時,下面的JS不受影響返干,繼續(xù)執(zhí)行兴枯。
如何實現(xiàn)?現(xiàn)在提供常用的幾種方法:

1.動態(tài)生成<script>標簽
<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body>
   <p>我是小仙女</p>
   <script type="text/javascript">
   (function(){
      var s=document.createElement("script");
      s.type="text/javascript";
      s.src="http://china-addthis.googlecode.com/svn/trunk/addthis.js";
      document.body.appendChild(s);
   })();
   </script>
   <script type="text/javascript" src='http://libs.baidu.com/jquery/2.0.0/jquery.min.js'></script>
   <script type="text/javascript">
      alert("hello world");
   </script>
</body>

但是上面的代碼還有點問題矩欠,這種加載方式在加載執(zhí)行完之前會阻止onload事件的觸發(fā)财剖,而現(xiàn)在很多頁面的代碼都在onload時執(zhí)行額外的渲染工作等,所以還是會阻塞部分頁面的初始化處理癌淮。

<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body>
   <p>我是小仙女</p>
   <script type="text/javascript">
   (function(){
      //function lazy(){
        var s=document.createElement("script");
        s.type="text/javascript";
        s.src="http://china-addthis.googlecode.com/svn/trunk/addthis.js";
        document.body.appendChild(s); 
     // }
     // window.addEventListener("load",lazy,false);
   })();
   window.onload=function(){
      alert("hello world");
   };
   </script>
   <script type="text/javascript" src='http://libs.baidu.com/jquery/2.0.0/jquery.min.js'></script>
</body>

上面帶注釋的代碼不能很好的渲染"hello world"躺坟,因為存在阻塞onload事件問題;可以把注釋去掉乳蓄,讓谷歌提供的JS在onload時才開始異步加載咪橙,這就解決了上述問題。

2.async屬性

async是HTML5的新屬性虚倒,該屬性規(guī)定一旦腳本可用美侦,則會異步執(zhí)行(一旦下載完畢就會立刻執(zhí)行)。
需要注意的是:async屬性僅適用于外部腳本(只有在使用src屬性時)魂奥。

<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body>
   <p>我是小仙女</p>
   <script type="text/javascript" src='http://china-addthis.googlecode.com/svn/trunk/addthis.js' async="async"></script>
   <script type="text/javascript" src='http://libs.baidu.com/jquery/2.0.0/jquery.min.js'></script>
   <script type="text/javascript">
      alert("hello world");
   </script>
</body>
3.defer屬性

defer屬性規(guī)定是否對腳本執(zhí)行進行延遲菠剩,直到頁面加載為止。
之前只有IE的hack支持defer屬性耻煤,現(xiàn)在H5開始全面支持defer屬性具壮。

<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body>
   <p>我是小仙女</p>
   <script type="text/javascript" src='http://china-addthis.googlecode.com/svn/trunk/addthis.js' defer="defer"></script>
   <script type="text/javascript" src='http://libs.baidu.com/jquery/2.0.0/jquery.min.js'></script>
   <script type="text/javascript">
      alert("hello world");
   </script>
</body>

asyncdefer看起來差不多呀准颓?而且經(jīng)常一起出現(xiàn)!來辨析一下

a.如果沒有asyncdefer屬性棺妓,那么瀏覽器會立即執(zhí)行當(dāng)前的JS腳本攘已,阻塞后面的腳本;
b.如果有async屬性涧郊,加載和渲染后續(xù)文檔的過程和當(dāng)前JS的加載與執(zhí)行并行進行(異步)贯被,它是亂序執(zhí)行的,不管你聲明的順序如何妆艘,只要它加載完了就會執(zhí)行彤灶;
c.如果有defer屬性,加載后續(xù)文檔元素的過程和JS的加載是并行進行(異步)的批旺,但是JS的執(zhí)行在所有元素解析完成之后進行幌陕,而且它是按照加載順序執(zhí)行腳本的
4.其他方式

a.XHR注入(通過XMLHttpRequest對象來獲取JS,然后創(chuàng)建一個script元素插入到DOM結(jié)構(gòu)中);
b.ajax eval(使用ajax得到腳本內(nèi)容汽煮,然后通過eval(xmlhttp.responseText)來運行腳本);
c.iframe等

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末搏熄,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子暇赤,更是在濱河造成了極大的恐慌心例,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鞋囊,死亡現(xiàn)場離奇詭異止后,居然都是意外死亡,警方通過查閱死者的電腦和手機溜腐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進店門译株,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人挺益,你說我怎么就攤上這事歉糜。” “怎么了望众?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵匪补,是天一觀的道長。 經(jīng)常有香客問我黍檩,道長叉袍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任刽酱,我火速辦了婚禮喳逛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘棵里。我一直安慰自己润文,他們只是感情好姐呐,可當(dāng)我...
    茶點故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著典蝌,像睡著了一般曙砂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上骏掀,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天鸠澈,我揣著相機與錄音,去河邊找鬼截驮。 笑死笑陈,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的葵袭。 我是一名探鬼主播涵妥,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼坡锡!你這毒婦竟也來了蓬网?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤鹉勒,失蹤者是張志新(化名)和其女友劉穎帆锋,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體禽额,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡窟坐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了绵疲。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,567評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡臣疑,死狀恐怖盔憨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情讯沈,我是刑警寧澤郁岩,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站缺狠,受9級特大地震影響问慎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜挤茄,卻給世界環(huán)境...
    茶點故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一如叼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧穷劈,春花似錦笼恰、人聲如沸踊沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽逼龟。三九已至,卻和暖如春追葡,著一層夾襖步出監(jiān)牢的瞬間腺律,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工宜肉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留匀钧,地道東北人。 一個月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓崖飘,卻偏偏與公主長得像榴捡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子朱浴,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,585評論 2 359

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

  • 本文總結(jié)一下瀏覽器在 javascript 的加載方式吊圾。關(guān)鍵詞:異步加載(async loading),延遲加載(...
    4ea0af17fd67閱讀 1,062評論 0 2
  • JavaScript腳本對現(xiàn)代網(wǎng)站來說是必不可少的翰蠢。當(dāng)用戶訪問站點项乒,需要下載各種資源,例如JS腳本梁沧,CSS檀何,圖片,...
    張歆琳閱讀 9,070評論 0 24
  • 默認情況javascript是同步加載的廷支,也就是javascript的加載時阻塞的频鉴,后面的元素要等待javascr...
    飛菲fly閱讀 8,280評論 1 4
  • 簡單介紹JavaScript的發(fā)展歷史 JavaScript因互聯(lián)網(wǎng)而生,回顧它的歷史要從瀏覽器的歷史講起恋拍。 19...
    _Dot912閱讀 492評論 0 3
  • Tif_Lib閱讀 470評論 0 1