日期:2014-05-16  浏览次数:20491 次

[分享]使用非阻塞方式并行加载Javascript,降低页面加载时间
1.目前绝大部分的浏览器都是采取阻塞方式(Scripts Block Downloads)加载Javascript文件的;
如下图所示:



只有当浏览器一个一个下载完所有的script文件时,才会开始并行下载其他资源(css, 图片,网页);
这种机制的好处就是我们可以随意在页面上使用那种JS库中的函数,因为页面肯定是在JS加裁之后呈现的,但是缺点也非常明显:一旦此Javascript文件过大,或网络连接不稳定,整个页面就会被阻塞一段时间,这里有一个 示例。

2.因此一般大型的网站都会采取非阻塞方式加载Javascript来提高性能(降低页面加载时间),Steve 在他的博文中提到了几种方法,如使用iframe, 动态添加script节点等来并行下载javascript文件。不过目前用得最多的应该还是动态添加script节点的方法。如下代码,出自 Nicholas的文章。
JScript code


function loadScript(url, callback){
    var script = document.createElement("script")
    script.type = "text/javascript";
    if (script.readyState){  //IE
        script.onreadystatechange = function(){
            if (script.readyState == "loaded" ||
                    script.readyState == "complete"){
                script.onreadystatechange = null;
                callback();
            }
        };
    } else {  //Others
        script.onload = function(){
            callback();
        };
    }
    script.src = url;
    document.body.appendChild(script);
}






3.但是这样带来了另外一个问题,就是在页面加载完的时间Javascript库可能还没有下载完,此时在页面上文件中的函数会出问题,不过解决方法也有很多:

A.在上文的loadScript中有一个callback函数,因此可以,定义一个较小loader的JS文件去加载其他较大的JS文件,并且会定义一个$wait函数,页面上这样使用:
$wait(function(){
? ……
});
当所以script都加载好时,$wait会直接执行function,如果没加载好,刚推进队列,加载好时再一起执行;这种方式的缺点是无法在较低版本的IE浏览器上执行,因为他们根本就没有script.onreadystatechange事件

B.在JS文件中绑定:即所有的Javascript和绑定代码都写到JS文件中,这种方式的特点是功能会直接跟DOM结构进行绑定,而无需配置,缺点都是整个Site都是统一配置,不利于多变的模块,示例:
//外部JS文件中
JScript code
(function($){
    //定义功能函数
    var RowSwitch = function(){
        var rowSwitch = this;

        rowSwitch.init = function(){
        ……
        };

        rowSwitch.bind = function(){
            $(".ptslist li a").click(function(e){
            ……
            });
        };
        ……
    };

    //绑定代码
    $(function(){
        var rowSwitch = new RowSwitch();
        rowSwitch.init();
        rowSwitch.bind();
    });

})(jQuery);


C.使用异步绑定,原理就是使用timer来检测要使用的对象是否可用,目前MSN使用的就类似这种方式,
//外部JS文件中, 定义jQuery插件
JScript code
(function ($) {
    var defaults = { …… };
    $.fn.rollOver = function (options) {
        var settings = $.extend(true, {}, defaults, options);
        });
    }
    $.fn.rollOver.defaults = defaults;
})(jQuery);
....
window.asyncCanary = 1; //文件结束标志


//页面中
JScript code
$async = function(canary){....}  //异步检测函数定义,这里会定义一个timer,隔一断时间就会检测标志是否已定义;

$async("asyncCanary", function(){  //检测asyncCanary,如果已定义则执行绑定
    $("#menubar").rollOver({hoverTxt:""....});
});



原文在此:http://blog.sina.com.cn/s/blog_54da57aa0100y1rr.html

------解决方案--------------------
支持下。。。
------解决方案--------------------
很好。。。
------解决方案--------------------
楼主可看看$LAB这个插件,就是异步加载js的