1. 程式人生 > >瀏覽器載入js的阻塞與非阻塞

瀏覽器載入js的阻塞與非阻塞

 這幾天因專案需求,要實現一系列的js檔案載入的問題,於是,就按照常規思路寫了一通,悲催的是測試後發現問題重重;

為什麼會有這麼多問題,仔細想來還是對瀏覽器載入js的原理理解不透,於是我翻閱了大量的資料和自己的一些實踐,總結出來以下的內容;

1、js在瀏覽器中的阻塞

  常規理解就是瀏覽器在載入js時候會阻塞瀏覽器的渲染操作,但頁面效能決定不希望我們在載入js的時候影響頁面的渲染,所以我們經常會把js檔案放到body之前去載入。而不會把它放在head裡去阻塞頁面的渲染。那麼問題來了,如果我們把js放在head裡,瀏覽器是怎麼去執行它的呢,是按順序載入還是並行載入呢?

其實在舊的瀏覽器下,都是按照先後順序來載入的,這就保證了載入的js依賴不會發生問題。但是新的瀏覽器已經開始允許並行載入js了,也就是說我可以同時下載js檔案,但是還是先後順序執行檔案的。

2、document.write 使用

我們一般會用document.write來生成一段廣告,經常這樣操作:document.write('<script id="posAD" type="text/javascript" src="http://192.168.3.107:888/control.js?platformcode=tcy&postioncode=A1&filecode=10030"><\/script>');

這樣操作也是阻塞的;有同學就問了,你這是外聯js,那麼內鏈的呢,我也做過測試,一樣的,同樣會阻塞。

這樣使用的時候一定要記住,要確保他是在dom ready之前去執行,否則它將會重新渲染整個頁面。

3、那麼如何實現非阻塞呢,那麼就需要動態載入js了,通過appendChild(script)這種方式去非同步載入js了,其實還可以用xhr物件來處理,但是這樣只能解決非跨域問題,跨域xhr就無能為力了。還有一種辦法就是新瀏覽器的defer 和 async 屬性了,這樣你把它寫到head裡也不會阻塞瀏覽器的渲染了。

於是在我明白上述的這樣東東之後,我簡單的實現一個動態載入js模組:

    //loadJS模組
    (function () {

      var loadJS = function (deps, callback) {
        if(typeof deps == 'string') {
          deps 
= [deps]; } var len = deps.length; var j = 0 ; var fn = function (){ j++; if(j == len) { callback.apply(window); } }; for(var i = 0 ; i < deps.length ; i++) { _loadMod(deps[i],fn); }; }; var _loadMod = function(url,fn) { var head = document.head || document.getElementsByTagName('head')[0] || document.documentElement; var script = document.createElement('script'); script.type = 'text/javascript'; script.charset = 'utf-8'; script.async = true; script.src = url; script.onload = script.onreadystatechange = function() { if (!script.readyState || script.readyState in {'loaded': 1, 'complete': 1}) { script.onload = script.onreadystatechange = null; fn(); head.removeChild(script); script = null; } } head.insertBefore(script, head.firstChild); } window.loadJS = loadJS; })();

以上內容也是我這兩天初步終結出來的,有不對的地方還希望各位童鞋指正。

有興趣的還可以參考這兩篇部落格:http://www.w3cfuns.com/blog-5443287-5401014.html 或則 http://www.cnblogs.com/hongcaomao/archive/2012/03/27/javascript_loadad.html