最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript異步加載問題總結(jié)

 更新時間:2018年02月17日 09:05:50   作者:韓子遲  
本篇文章給大家分享了作者在學(xué)習(xí)JavaScript異步加載中遇到的問題,總結(jié)后給出了詳細(xì)的處理方案,有興趣的朋友可以學(xué)習(xí)下。

同步加載的問題

默認(rèn)的js是同步加載的,這里的“加載”可以理解成是解析、執(zhí)行,而不是“下載”,在最新版本的瀏覽器中,瀏覽器對于代碼請求的資源都是瀑布式的加載,而不是阻塞式的,但是js的執(zhí)行總是阻塞的。這會引起什么問題呢?如果我的index頁面要加載一些js,但是其中的某個請求遲遲得不到響應(yīng),于是阻塞了后面的js代碼的執(zhí)行(同步加載),同時頁面渲染也不能繼續(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文件,頁面的主體是一個簡單的字符串,但是代碼執(zhí)行后頁面遲遲都是空白,為何?因為請求的js遲遲無法加載(可能由于谷歌被墻等原因),于是阻塞了后面的代碼的執(zhí)行,頁面得不到渲染??赡苣銜嶙h,把js代碼放到</body>前不就能先渲染頁面了!好方法,我們嘗試著將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>

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

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ǔ)上簡單加了一段代碼,但是"hello world"遲遲無法在控制臺輸出,顯然前面的js請求阻塞了后面代碼的加載,我們恍然大悟,改變js的加載位置只能改變頁面的渲染,然而對于js的加載并沒有什么卵用,js還是會阻塞。

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

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

最常見的做法是動態(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>

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

<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 時才開始異步加載。這樣就解決了阻塞 onload 事件觸發(fā)的問題。

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

以上似乎能較好解決這個問題,但是html5提供了更簡便的方法,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ī)定一旦腳本可用,則會異步執(zhí)行(一旦下載完畢就會立刻執(zhí)行)。

需要注意的是async 屬性僅適用于外部腳本(只有在使用 src 屬性時)

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>

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

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

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

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

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

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

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

  1. defer 和 async 在網(wǎng)絡(luò)讀取(下載)這塊兒是一樣的,都是異步的(相較于 HTML 解析)
  2. 它倆的差別在于腳本下載完之后何時執(zhí)行,顯然 defer 是最接近我們對于應(yīng)用腳本加載和執(zhí)行的要求的
  3. 關(guān)于 defer,此圖未盡之處在于它是按照加載順序執(zhí)行腳本的,這一點要善加利用
  4. async 則是一個亂序執(zhí)行的主,反正對它來說腳本的加載和執(zhí)行是緊緊挨著的,所以不管你聲明的順序如何,只要它加載完了就會立刻執(zhí)行
  5. 仔細(xì)想想,async 對于應(yīng)用腳本的用處不大,因為它完全不考慮依賴(哪怕是最低級的順序執(zhí)行),不過它對于那些可以不依賴任何腳本或不被任何腳本依賴的腳本來說卻是非常合適的,最典型的例子:Google Analytics

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

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í)行這段代碼,控制臺的“hello world”也會遲遲得不到結(jié)果。所以我覺得還是async好用,如果要考慮依賴的話,可以選擇requirejs、seajs等模塊加載器。

總結(jié)

JavaScript的異步加載還有一些方式,比如:AJAX eval(使用AJAX得到腳本內(nèi)容,然后通過eval(xmlhttp.responseText)來運行腳本)、iframe方式等。

以上理解如果有出入,還望指出~感謝大家對腳本之家的支持。

相關(guān)文章

  • Javascript之高級數(shù)組API的使用實例

    Javascript之高級數(shù)組API的使用實例

    今天小編就為大家分享一篇關(guān)于Javascript之高級數(shù)組API的使用實例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • JavaScript作用域鏈?zhǔn)褂媒榻B

    JavaScript作用域鏈?zhǔn)褂媒榻B

    作用域就是變量和函數(shù)的可訪問范圍,控制著變量和函數(shù)的可見性與生命周期,在JavaScript中變量的作用域有全局作用域和局部作用域
    2013-08-08
  • JavaScript面向?qū)ο蠓謱铀季S全面解析

    JavaScript面向?qū)ο蠓謱铀季S全面解析

    這篇文章主要介紹了JavaScript面向?qū)ο蠓謱铀季S,js本身不是面向?qū)ο笳Z言,在我們實際開發(fā)中其實很少用到面向?qū)ο笏枷?。下文關(guān)于js面向?qū)ο笾R給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧
    2016-11-11
  • 微信小程序動態(tài)顯示項目倒計時效果

    微信小程序動態(tài)顯示項目倒計時效果

    這篇文章主要為大家詳細(xì)介紹了微信小程序動態(tài)顯示項目倒計時,格式如4天7小時58分鐘39秒,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • window.location和document.location的區(qū)別分析

    window.location和document.location的區(qū)別分析

    用戶不能改變document.location(因為這是當(dāng)前顯示文檔的位置)。但是,可以改變window.location (用其它文檔取代當(dāng)前文檔)window.location本身也是一個對象,而document.location不是對象
    2008-12-12
  • JavaScript函數(shù)聲明和函數(shù)表達式的區(qū)別

    JavaScript函數(shù)聲明和函數(shù)表達式的區(qū)別

    這篇文章主要介紹了JavaScript函數(shù)聲明和函數(shù)表達式的區(qū)別,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-06-06
  • JS獲取本周周一,周末及獲取任意時間的周一周末功能示例

    JS獲取本周周一,周末及獲取任意時間的周一周末功能示例

    這篇文章主要介紹了JS獲取本周周一,周末及獲取任意時間的周一周末功能,結(jié)合實例形式分析了js通過擴展實現(xiàn)針對日期的運算相關(guān)技巧,需要的朋友可以參考下
    2017-02-02
  • JavaScript中自定義事件用法分析

    JavaScript中自定義事件用法分析

    這篇文章主要介紹了JavaScript中自定義事件用法,較為詳細(xì)的分析了自定義事件的原理與具體用法,具有一定的參考借鑒價值,需要的朋友可以參考下
    2014-12-12
  • Next.js路由組使用之組織路由結(jié)構(gòu)示例詳解

    Next.js路由組使用之組織路由結(jié)構(gòu)示例詳解

    這篇文章主要為大家介紹了Next.js路由組使用之組織路由結(jié)構(gòu)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-10-10
  • 使用原生js編寫一個簡單的框選功能方法

    使用原生js編寫一個簡單的框選功能方法

    這篇文章主要介紹了使用原生js編寫一個簡單的框選功能方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05

最新評論

吴川市| 象州县| 小金县| 资阳市| 格尔木市| 安阳市| 繁昌县| 成安县| 赣榆县| 迁西县| 绥芬河市| 盈江县| 惠东县| 洛阳市| 南江县| 上饶县| 陆良县| 祁东县| 乐亭县| 闽清县| 响水县| 竹山县| 仁化县| 鄂尔多斯市| 东山县| 济南市| 文成县| 大英县| 开鲁县| 清水河县| 赤水市| 金山区| 巨鹿县| 平果县| 昌黎县| 武清区| 于都县| 南郑县| 玉环县| 上思县| 洱源县|