脚本无阻塞加载

来源:互联网 发布:使用u盘安装linux系统 编辑:程序博客网 时间:2024/05/17 01:32






                    (图片来源:http://www.cnblogs.com/sharpxiajun/p/4072396.html)
     
    这是清除浏览器缓存后,第一次访问百度首页的场景,在Firefox的瀑布图中可以看到:javascript文件下载完毕后,有一段时间没有请求处理。这段时间过后,请求才会接着执行,这段时间就是HTTP请求阻塞

    当浏览器遇到<script>标签时,浏览器会停止处理页面,先执行Javascript代码,然后再继续解析和渲染页面。在这个过程中,页面和用户的交互完全被阻塞了。通常表现为显示空白页面,用户无法浏览内容。

    现在的浏览器都支持并行下载文件,比如上图同时下载多个图片。而且,IE8 、FireFox3.5、Safari4和Chrome2都支持并行下载javascript文件,但是javascript文件的下载会阻塞其他资源的下载。尽管脚本的下载过程不会相互影响,但是页面仍然需要等待javascript的执行完毕才能继续。所以,新浏览器通过并行下载提高了性能,但是脚本阻塞问题仍然没有解决。

解决方法有:

(1)把<script>标签放到</body>闭合之前

  由于脚本会阻塞其他资源的下载,因此推荐把所有的<script>标签尽可能的放到<body>标签的底部。

(2)脚本合并,减少<script>标签的数量  

  每次遇到<script>标签,浏览器都要发一次HTTP请求。而HTTP请求耗时是web性能的最大的影响之一。

(3)动态脚本加载

       忙指示(忙指示现象有:浏览器选项卡的旋转圆圈,鼠标变成漏斗状,浏览器左下状态栏显示正在加载某某url)标记结束了,就表明页面的加载操作结束了,为了防止js脚本阻塞页面的加载。我们就要让那些不用于页面初始化展示的js代码的加载和执行在浏览器忙指示结束后触发。结束的标志就是onload事件触发,因此我们可以把那些有页面加载无关的js脚本放到onload事件里。


<pre name="code" class="javascript"> var script=document.createElemetn("script");  script.type="text/javascript";  script.src="file.js";;  document.getElementsByTagName("head").appendChild(script);


使用动态脚本这种技术重点在于:文件的下载和执行过程不会阻塞页面其他进程。通常要把新创建的<script>标签添加到<head>标签里比添加到<body>标签里更保险。但是这种情况下,必须跟踪并确保脚本下载完成并准备就绪。
   标准浏览器:

  符合w3c标准的浏览器,script元素接收完成式,触发一个load事件。

var script =document.createElement("div");script.type="text/javascript";script.onload=function(){  alert("ok");};script.src="file.js";document.getElementsByTagName("head")[0].appendChild(script);

IE支持另外一种实现方式,触发readystatechange事件。<script>元素提供一个readyState属性,它的值在外链下载过程中不同阶段发生变化,属性有五个值:

  “uninitializd”   初始状态

   “loading”       开始下载
  
   “loaded”       下载完成

   “interactive”  数据下载完成但尚不可用

    “complete”  所有数据已准备就绪


最有用的的两个状态是:"loaded"和"complete"。

var script=document.createElement("script");script.type="text/javascript";//IEscript.onreadystatechange=function(){   if(script.readyState=="loaded"||script.readyState="complete"){   script.onreadystatechange=null;   alert("ok"); }}

兼容标准及IE浏览器:

function loadScript(url ,callback){    var script=document.createElement("script");    script.src="text/javascript";          if(script.readyState){//IE         script.onreadyStateChange=function(){         if(script.readyState=="loaded"||script.readyState=="complete"){                    script.onreadystatechange=null;                             callback();                }            };    }else{//其他浏览器     script.onload=function(){        callback();     };  }      script.src=url;      document.getElementsByTagName("head")[0].appendChild(script); }
  
单个文件:

loadScript("file1.js",function(){  alert("ok")});

添加多个文件:
loadScript("file1.js",function(){      loadScript("file2.js",function(){         loadScript("file3.js",function(){          alert("ok");          });      });  });

添加多个文件会对管理带来困难,可以借助jquery的$.Deferred()和$.when()避免回调地狱。(http://blog.csdn.net/vuturn/article/details/45024767)

推荐的无阻塞模式

<script type="text/javascript" src="test.js"></script><script type="text/javascript">loadScript("file.js",function(){   alert("ok");}); </script>


参考:(http://www.cnblogs.com/sharpxiajun/p/4072396.html
              《高性能JavaScript 》


0 0
原创粉丝点击