JS异步加载的三种方式

1、同步加载

  咱们平时使用的最多的一种方式。javascript

<script src="http://yourdomain.com/script.js"></script>
<script src="http://yourdomain.com/script.js"></script>

  同步模式,又称阻塞模式,会阻止浏览器的后续处理,中止后续的解析,只有当当前加载完成,才能进行下一步操做。因此默认同步执行才是安全的。但这样若是js中有输出document内容、修改dom、重定向等行为,就会形成页面堵塞。因此通常建议把<script>标签放在<body>结尾处,这样尽量减小页面阻塞。css


2、异步加载

  异步加载又叫非阻塞加载,浏览器在下载执行js的同时,还会继续进行后续页面的处理。主要有三种方式。html

  方法一:也叫Script DOM Element

1 (function(){
2     var scriptEle = document.createElement("script");
3     scriptEle.type = "text/javasctipt";
4     scriptEle.async = true;
5     scriptEle.src = "http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js";
6     var x = document.getElementsByTagName("head")[0];
7     x.insertBefore(scriptEle, x.firstChild);        
8  })();

  <async>属性是HTML5中新增的异步支持。此方法被称为Script DOM Element 方法。Google Analytics 和 Google+ Badge 都使用了这种异步加载代码html5

1 (function(){;
2     var ga = document.createElement('script'); 
3     ga.type = 'text/javascript'; 
4     ga.async = true; 
5     ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; 
6     var s = document.getElementsByTagName('script')[0]; 
7     s.parentNode.insertBefore(ga, s); 
8 })();

  可是这种加载方式执行完以前会阻止onload事件的触发,而如今不少页面的代码都在onload时还执行额外的渲染工做,因此仍是会阻塞部分页面的初始化处理。java

  方法二:onload时的异步加载

 1 (function(){
 2     if(window.attachEvent){
 3         window.attachEvent("load", asyncLoad);
 4     }else{
 5         window.addEventListener("load", asyncLoad);
 6     }
 7     var asyncLoad = function(){
 8         var ga = document.createElement('script'); 
 9         ga.type = 'text/javascript'; 
10         ga.async = true; 
11         ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; 
12         var s = document.getElementsByTagName('script')[0]; 
13         s.parentNode.insertBefore(ga, s);
14     }
15 )();

  这种方法只是把插入script的方法放在一个函数里面,而后放在window的onload方法里面执行,这样就解决了阻塞onload事件触发的问题。jquery

  注:DOMContentLoaded与load的区别。前者是在document已经解析完成,页面中的dom元素可用,可是页面中的图片,视频,音频等资源未加载完,做用同jQuery中的ready事件;后者的区别在于页面全部资源所有加载完毕。ajax

  方法三:其余方法

  因为JavaScript的动态性,还有不少异步加载方法: XHR Injection、 XHR Eval、 Script In Iframe、 Script defer属性、 document.write(script tag)。浏览器

  XHR Injection(XHR 注入):经过XMLHttpRequest来获取javascript,而后建立一个script元素插入到DOM结构中。ajax请求成功后设置script.text为请求成功后返回的responseText。缓存

 1  //获取XMLHttpRequest对象,考虑兼容性。
 2     var getXmlHttp = function(){
 3         var obj;
 4         if (window.XMLHttpRequest)
 5             obj = new XMLHttpRequest();
 6         else
 7             obj = new ActiveXObject("Microsoft.XMLHTTP");
 8         return obj;
 9     };  
10     //采用Http请求get方式;open()方法的第三个参数表示采用异步(true)仍是同步(false)处理
11     var xmlHttp = getXmlHttp();
12     xmlHttp.open("GET", "http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js", true);
13     xmlHttp.send(); 
14     xmlHttp.onreadystatechange = function(){
15         if (xmlHttp.readyState == 4 && xmlHttp.status == 200){
16             var script = document.createElement("script");
17             script.text = xmlHttp.responseText;
18             document.getElementsByTagName("head")[0].appendChild(script);
19         }
20     }        

  XHR Eval:与XHR Injection对responseText的执行方式不一样,直接把responseText放在eval()函数里面执行。安全

 1  //获取XMLHttpRequest对象,考虑兼容性。
 2     var getXmlHttp = function(){
 3         var obj;
 4         if (window.XMLHttpRequest)
 5             obj = new XMLHttpRequest();
 6         else
 7             obj = new ActiveXObject("Microsoft.XMLHTTP");
 8         return obj;
 9     };  
10     //采用Http请求get方式;open()方法的第三个参数表示采用异步(true)仍是同步(false)处理
11     var xmlHttp = getXmlHttp();
12     xmlHttp.open("GET", "http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js", true);
13     xmlHttp.send(); 
14     xmlHttp.onreadystatechange = function(){
15         if (xmlHttp.readyState == 4 && xmlHttp.status == 200){
16             eval(xmlHttp.responseText);
17             //alert($);//能够弹出$,代表JS已经加载进来。click事件放在其它出会出问题,应该是还没加载进来
18             $("#btn1").click(function(){
19                 alert($(this).text());
20             });
21         }
22     }        

  Script In Irame:在父窗口插入一个iframe元素,而后再iframe中执行加载JS的操做。

1  var insertJS = function(){alert(2)};
2     var iframe = document.createElement("iframe");
3     document.body.appendChild(iframe);
4     var doc = iframe.contentWindow.document;//获取iframe中的window要用contentWindow属性。
5     doc.open();
6     doc.write("<script>var insertJS = function(){};<\/script><body onload='insertJS()'></body>"); 7  doc.close();

  GMail Mobile:业内JS内容被注释,因此不会执行,在须要的时候,获取script中的text内容去掉注释,调用eval()执行。

1 <script type="text/javascript"> 
2     /* 
3  var ... 4     */ 
5     </script>

HTML5新属性:async和defer属性

  defer属性:IE4.0就出现。defer属声明脚本中将不会有document.write和dom修改。浏览器会并行下载其余有defer属性的script。而不会阻塞页面后续处理。注:全部的defer脚本必须保证按顺序执行的。

  <script type="text/javascript" defer></script>

  Firefox 3.六、Opera 10.五、IE 9和最新的Chrome和Safari都支持async属性。能够同时使用async和defer,这样IE 4以后的全部IE都支持异步加载。

  没有async属性,script将当即获取(下载)并执行,期间阻塞了浏览器的后续处理。若是有async属性,那么script将被异步下载并执行,同时浏览器继续后续的处理。


3、延迟加载

  有些JS代码在某些状况在须要使用,并非页面初始化的时候就要用到。延迟加载就是为了解决这个问题。将JS切分红许多模块,页面初始化时只加载须要当即执行的JS,而后其它JS的加载延迟到第一次须要用到的时候再加载。相似图片的延迟加载。

  JS的加载分为两个部分:下载和执行。异步加载只是解决了下载的问题,可是代码在下载完成后就会当即执行,在执行过程当中浏览器处于阻塞状态,响应不了任何需求。

  解决思路:为了解决JS延迟加载的问题,能够利用异步加载缓存起来,但不当即执行,须要的时候在执行。如何进行缓存呢?将JS内容做为Image或者Object对象加载缓存起来,因此不会当即执行,而后在第一次须要的时候在执行。

  

  1:模拟较长的下载时间:

    利用thread让其sleep一段时间在执行下载操做。

  2:模拟较长的JS代码执行时间   

    var start = Number(new Date());

    while(start + 5000 > Number(new Date())){//执行JS}

    这段代码将使JS执行5秒才完成!


JS延迟加载机制(LazyLoad):简单来讲,就是在浏览器滚动到某个位置在触发相关的函数,实现页面元素的加载或者某些动做的执行。如何实现浏览器滚动位置的检测呢?能够经过一个定时器来实现,经过比较某一时刻页面目标节点位置和浏览器滚动条高度来判断是否须要执行函数。
相关文章
相关标签/搜索