?處理JavaScript異步加載的注意事項(xiàng)有哪些-創(chuàng)新互聯(lián)

這篇文章給大家分享的是有關(guān)處理JavaScript異步加載的注意事項(xiàng)有哪些的內(nèi)容。小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧。

成都創(chuàng)新互聯(lián)公司長(zhǎng)期為上1000+客戶(hù)提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開(kāi)放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為義烏企業(yè)提供專(zhuān)業(yè)的成都做網(wǎng)站、成都網(wǎng)站建設(shè),義烏網(wǎng)站改版等技術(shù)服務(wù)。擁有十年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開(kāi)發(fā)。

處理JavaScript異步加載詳解的注意事項(xiàng)有哪些

同步加載的問(wèn)題

默認(rèn)的js是同步加載的,這里的“加載”可以理解成是解析、執(zhí)行,而不是“下載”,在新版本的瀏覽器中,瀏覽器對(duì)于代碼請(qǐng)求的資源都是瀑布式的加載,而不是阻塞式的,但是js的執(zhí)行總是阻塞的。這會(huì)引起什么問(wèn)題呢?如果我的index頁(yè)面要加載一些js,但是其中的某個(gè)請(qǐng)求遲遲得不到響應(yīng),于是阻塞了后面的js代碼的執(zhí)行(同步加載),同時(shí)頁(yè)面渲染也不能繼續(xù)(如果js引入是在head標(biāo)簽后)。

<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>
this is a test

比如上面的這段代碼,保存為index.html文件,頁(yè)面的主體是一個(gè)簡(jiǎn)單的字符串,但是代碼執(zhí)行后頁(yè)面遲遲都是空白,為何?因?yàn)檎?qǐng)求的js遲遲無(wú)法加載(可能由于谷歌被墻等原因),于是阻塞了后面的代碼的執(zhí)行,頁(yè)面得不到渲染??赡苣銜?huì)提議,把js代碼放到</body>前不就能先渲染頁(yè)面了!好方法,我們嘗試著將js放后面:

this is a test
<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>

頁(yè)面瞬間被渲染,“this is a test"也很快出現(xiàn)在前臺(tái),世界似乎平靜了,可是:

this is a test
<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">
 console.log('hello world');
</script>

在前面代碼的基礎(chǔ)上簡(jiǎn)單加了一段代碼,但是"hello world"遲遲無(wú)法在控制臺(tái)輸出,顯然前面的js請(qǐng)求阻塞了后面代碼的加載,我們恍然大悟,改變js的加載位置只能改變頁(yè)面的渲染,然而對(duì)于js的加載并沒(méi)有什么卵用,js還是會(huì)阻塞。

實(shí)現(xiàn)js異步加載

我們的要求似乎很簡(jiǎn)單,能在頁(yè)面加載的同時(shí),在控制臺(tái)輸出字符串即可,再講的通俗一點(diǎn),就是在請(qǐng)求第一段谷歌提供的js的同時(shí),繼續(xù)執(zhí)行下面的js,也就是實(shí)現(xiàn)js的異步加載。

最常見(jiàn)的做法是動(dòng)態(tài)生成script標(biāo)簽:

<body>
 this is a test
 <script type="text/javascript">
  ~function() {
   var s = document.createElement('script');
   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">
  console.log('hello world');
 </script>
</body>

但是還是有點(diǎn)問(wèn)題,這種加載方式在加載執(zhí)行完之前會(huì)阻止 onload 事件的觸發(fā),而現(xiàn)在很多頁(yè)面的代碼都在 onload 時(shí)還要執(zhí)行額外的渲染工作等,所以還是會(huì)阻塞部分頁(yè)面的初始化處理:

<body>
 this is a test
 <script type="text/javascript">
  ~function() {
   // function async_load() {
    var s = document.createElement('script');
    s.src = 'http://china-addthis.googlecode.com/svn/trunk/addthis.js';
    document.body.appendChild(s);
   // }
   // window.addEventListener('load', async_load, false);
  }();
  window.onload = function() {
   var txt = document.createTextNode(' hello world');
   document.body.appendChild(txt);
  };
 </script>
 <script type="text/javascript" src='http://libs.baidu.com/jquery/2.0.0/jquery.min.js'></script>
</body>

比如上面的代碼不能很好地渲染”hello world”,我們只需將注釋去掉就可以了,讓谷歌提供的js在onload 時(shí)才開(kāi)始異步加載。這樣就解決了阻塞 onload 事件觸發(fā)的問(wèn)題。

補(bǔ)充DOMContentLoaded 與 OnLoad 事件 DOMContentLoaded : 頁(yè)面(document)已經(jīng)解析完成,頁(yè)面中的dom元素已經(jīng)可用。但是頁(yè)面中引用的圖片、subframe可能還沒(méi)有加載完。 OnLoad:頁(yè)面的所有資源都加載完畢(包括圖片)。瀏覽器的載入進(jìn)度在這時(shí)才停止。這兩個(gè)時(shí)間點(diǎn)將頁(yè)面加載的timeline分成了三個(gè)階段。

以上似乎能較好解決這個(gè)問(wèn)題,但是html5提供了更簡(jiǎn)便的方法,async屬性!

this is a test
<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">
 console.log('hello world');
</script>

async是html5的新屬性,async 屬性規(guī)定一旦腳本可用,則會(huì)異步執(zhí)行(一旦下載完畢就會(huì)立刻執(zhí)行)。

需要注意的是async 屬性?xún)H適用于外部腳本(只有在使用 src 屬性時(shí))

defer屬性常常和async一起提起:

this is a test
<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">
 console.log('hello world');
</script>

似乎實(shí)現(xiàn)效果差不多,但是真的一樣嗎?我們來(lái)看看defer屬性的定義。

以前的defer只支持ie的hack,現(xiàn)在html5的出現(xiàn)開(kāi)始全面支持defer。defer 屬性規(guī)定當(dāng)頁(yè)面已完成加載后,才會(huì)執(zhí)行腳本。defer 屬性?xún)H適用于外部腳本(只有在使用 src 屬性時(shí))。ps:ie支持的defer似乎并非如此,因?yàn)閷?duì)ie無(wú)感,不深究,有興趣的可以去查閱相關(guān)資料。

既然async和defer經(jīng)常一起出現(xiàn),那么辨析一下吧!

如果沒(méi)有async和defer屬性(賦值為true,下同),那么瀏覽器會(huì)立即執(zhí)行當(dāng)前的js腳本,阻塞后面的腳本;如果有async屬性,加載和渲染后續(xù)文檔元素的過(guò)程將和當(dāng)前js的加載與執(zhí)行并行進(jìn)行(異步);如果有defer屬性,那么加載后續(xù)文檔元素的過(guò)程將和 script.js 的加載并行進(jìn)行(異步),但是 script.js 的執(zhí)行要在所有元素(DOM)解析完成之后,DOMContentLoaded 事件觸發(fā)之前完成。

來(lái)看一張網(wǎng)上盜的圖:

?處理JavaScript異步加載的注意事項(xiàng)有哪些

藍(lán)色線代表網(wǎng)絡(luò)讀取,紅色線代表執(zhí)行時(shí)間,這倆都是針對(duì)腳本的;綠色線代表 HTML 解析。

此圖告訴我們以下幾個(gè)要點(diǎn)(摘自defer和async的區(qū)別):

  1. defer 和 async 在網(wǎng)絡(luò)讀?。ㄏ螺d)這塊兒是一樣的,都是異步的(相較于 HTML 解析)

  2. 它倆的差別在于腳本下載完之后何時(shí)執(zhí)行,顯然 defer 是最接近我們對(duì)于應(yīng)用腳本加載和執(zhí)行的要求的

  3. 關(guān)于 defer,此圖未盡之處在于它是按照加載順序執(zhí)行腳本的,這一點(diǎn)要善加利用

  4. async 則是一個(gè)亂序執(zhí)行的主,反正對(duì)它來(lái)說(shuō)腳本的加載和執(zhí)行是緊緊挨著的,所以不管你聲明的順序如何,只要它加載完了就會(huì)立刻執(zhí)行

  5. 仔細(xì)想想,async 對(duì)于應(yīng)用腳本的用處不大,因?yàn)樗耆豢紤]依賴(lài)(哪怕是最低級(jí)的順序執(zhí)行),不過(guò)它對(duì)于那些可以不依賴(lài)任何腳本或不被任何腳本依賴(lài)的腳本來(lái)說(shuō)卻是非常合適的,最典型的例子:Google Analytics

但是在我看來(lái)(以下個(gè)人理解,如有出入還望指出),defer在異步加載上的應(yīng)用并不會(huì)比async廣。async的英文解釋是異步,該屬性作用在腳本上,使得腳本加載(下載)完后隨即開(kāi)始執(zhí)行,和動(dòng)態(tài)插入script標(biāo)簽作用類(lèi)似(async只支持h6,后者能兼容瀏覽器);而defer的英文解釋是延遲,作用也和字面解釋類(lèi)似,延遲腳本的執(zhí)行,使得dom元素加載完后才開(kāi)始有序執(zhí)行腳本,因?yàn)橛行?,所以?huì)帶來(lái)另一個(gè)問(wèn)題:

this is a test
<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' defer='defer'></script>
<script type="text/javascript" src='index.js' defer='defer'></script>
console.log('hello world');

如果執(zhí)行這段代碼,控制臺(tái)的“hello world”也會(huì)遲遲得不到結(jié)果。所以我覺(jué)得還是async好用,如果要考慮依賴(lài)的話,可以選擇requirejs、seajs等模塊加載器。

感謝各位的閱讀!關(guān)于“處理JavaScript異步加載的注意事項(xiàng)有哪些”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

文章題目:?處理JavaScript異步加載的注意事項(xiàng)有哪些-創(chuàng)新互聯(lián)
鏈接地址:http://muchs.cn/article34/cedepe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制網(wǎng)站、App開(kāi)發(fā)、全網(wǎng)營(yíng)銷(xiāo)推廣、外貿(mào)網(wǎng)站建設(shè)建站公司、定制開(kāi)發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)