同步載入與非同步載入

來源:互聯網
上載者:User

這幾天一直在忙項目上線的問題,碰到了好多問題,比如非同步載入、事件冒泡、瀏覽器緩衝。這篇文章主要是檔案的同步載入和非同步載入。

先說下我碰到的問題:項目要接入到支付寶城市服務中,但是安卓和ios設定支付寶的導覽列內容有差異。安卓和ios都是拿頁面的title設定導覽列的內容,但是安卓支援用js動態修改title,ios是在頁面初始化時會預設拿title作為導覽列內容,初始化後用JS動態修改無效。支付寶提供了設定支付寶導航的jsAPI,需要載入兩個檔案,我之前是在項目中直接載入這連個檔案,在調用它提供的方法,沒問題完美設定。但是後來我感覺這樣不好我不是每個輸出的商戶都需要設定,所以我用navigator.userAgent判斷是不是在支付寶用戶端開啟,在動態添加這兩個JS檔案,在這就出現問題了,你動態添加完JS後,馬上執行裡面的方法有時會出現錯誤,說明你還沒有載入成功時就執行了方法。

這裡就是我們經常說的同步載入與非同步載入:

1. 同步載入

我們平時最常使用的就是這種同步載入形式:

<script src="js/jQuery.js"></script> 

同步模式,又稱阻塞模式,會阻止瀏覽器的後續處理,停止了後續的解析,因此停止了後續的檔案載入(如映像)、渲染、代碼執行。

 js 之所以要同步執行,是因為 js 中可能有輸出 document 內容、修改dom、重新導向等行為,所以預設同步執行才是安全的。

以前的一般建議是把<script>放在頁面末尾</body>之前,這樣儘可能減少這種阻塞行為,而先讓頁面展示出來。

簡單說:載入的網路 timeline 是瀑布模型,而非同步載入的 timeline 是並行存取模型。

2. 常見非同步載入(Script DOM Element)

原生方法

(function() {
     var s = document.createElement('script');
     s.type = 'text/javascript';
     s.async = true;
     s.src = 'js/jQuery.js';
     var x = document.getElementsByTagName('script')[0];
     x.parentNode.insertBefore(s, x);
 })();

jQuery方法

$("head").append(“jQuery.js”)


非同步載入又叫非阻塞,瀏覽器在下載執行 js 同時,還會繼續進行後續頁面的處理。

這種方法是在頁面中<script>標籤內,用 js 建立一個 script 元素並插入到 document 中。這樣就做到了非阻塞的下載 js 代碼。

3. onload 時的非同步載入

(function() {
     function async_load(){
         var s = document.createElement('script');
         s.type = 'text/javascript';
         s.async = true;
         s.src = 'js/jQuery.js';
         var x = document.getElementsByTagName('script')[0];
         x.parentNode.insertBefore(s, x);
     }
     if (window.attachEvent)
         window.attachEvent('onload', async_load);
     else
         window.addEventListener('load', async_load, false);
 })(); 

這和前面的方式差不多,但關鍵是它不是立即開始非同步載入 js ,而是在 onload 時才開始非同步載入。這樣就解決了阻塞 onload 事件觸發的問題。

補充:DOMContentLoaded 與 OnLoad 事件

DOMContentLoaded : 頁面(document)已經解析完成,頁面中的dom元素已經可用。但是頁面中引用的圖片、subframe可能還沒有載入完。

OnLoad:頁面的所有資源都載入完畢(包括圖片)。瀏覽器的載入進度在這時才停止。

4. jQuery的非同步載入

jQuery.getScript(url, [callback])

參數:url:待載入 JS 檔案地址。

callback:成功載入後回呼函數。

$.getScript("test.js", function(){

alert("Script loaded and executed.");

});

這和前面的方法差不多載入 test.js 成功後,調用方法顯示資訊。

5、async 和 defer 屬性

1. defer 屬性

<script src="js/jQuery.js" defer></script> 

defer屬性聲明這個指令碼中將不會有 document.write 或 dom 修改。

瀏覽器將會並行下載 file.js 和其它有 defer 屬性的script,而不會阻塞頁面後續處理。

defer屬性在IE 4.0中就實現了,超過13年了。Firefox 從 3.5 開始支援defer屬性 。

註:所有的defer 指令碼保證是按順序依次執行的。

2. async 屬性

<script src="js/jQuery.js" async></script> 

async屬性是HTML5新增的。作用和defer類似,但是它將在下載後儘快執行,不能保證指令碼會按順序執行。它們將在onload 事件之前完成。

Firefox 3.6、Opera 10.5、IE 9 和 最新的Chrome 和 Safari 都支援 async 屬性。可以同時使用 async 和 defer,這樣IE 4之後的所有 IE 都支援非同步載入。

3. 詳細解釋

<script> 標籤在 HTML 4.01 與 HTML5 的區別:

· type 屬性在HTML 4中是必須的,在HTML5中是可選的。

· async 屬性是HTML5中新增的。

· 個別屬性(xml:space)在HTML5中不支援。

說明:

1. 沒有 async 屬性,script 將立即擷取(下載)並執行,然後才繼續後面的處理,這期間阻塞了瀏覽器的後續處理。

2. 如果有 async 屬性,那麼 script 將被非同步下載並執行,同時瀏覽器繼續後續的處理。

3. HTML4中就有了defer屬性,它提示瀏覽器這個 script 不會產生任何文件項目(沒有document.write),因此瀏覽器會繼續後續處理和渲染。

4. 如果沒有 async 屬性 但是有 defer 屬性,那麼script 將在頁面parse之後執行。

5. 如果同時設定了二者,那麼 defer 屬性主要是為了讓不支援 async 屬性的老瀏覽器按照原來的 defer 方式處理,而不是同步方式。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.