详解JS异步加载的三种方式

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

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

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

二:异步加载

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

方法一:也叫Script DOM Element

(function(){ var scriptEle = document.createElement("script"); scriptEle.type = "text/javasctipt"; scriptEle.async = true; scriptEle.src = "http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js"; var x = document.getElementsByTagName("head")[0]; x.insertBefore(scriptEle, x.firstChild); })(); <async>属性是HTML5中新增的异步支持。此方法被称为Script DOM Element 方法。Google Analytics 和 Google+ Badge 都使用了这种异步加载代码 (function(){; var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })();

但是这种加载方式执行完之前会阻止onload事件的触发,而现在很多页面的代码都在onload时还执行额外的渲染工作,所以还是会阻塞部分页面的初始化处理。

方法二:onload时的异步加载

(function(){ if(window.attachEvent){ window.attachEvent("load", asyncLoad); }else{ window.addEventListener("load", asyncLoad); } var asyncLoad = function(){ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); } )();

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

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

方法三:其他方法

由于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。

//获取XMLHttpRequest对象,考虑兼容性。 var getXmlHttp = function(){ var obj; if (window.XMLHttpRequest) obj = new XMLHttpRequest(); else obj = new ActiveXObject("Microsoft.XMLHTTP"); return obj; }; //采用Http请求get方式;open()方法的第三个参数表示采用异步(true)还是同步(false)处理 var xmlHttp = getXmlHttp(); xmlHttp.open("GET", "http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js", true); xmlHttp.send(); xmlHttp.onreadystatechange = function(){ if (xmlHttp.readyState == 4 && xmlHttp.status == 200){ var script = document.createElement("script"); script.text = xmlHttp.responseText; document.getElementsByTagName("head")[0].appendChild(script); } } XHR Eval:与XHR Injection对responseText的执行方式不同,直接把responseText放在eval()函数里面执行。 //获取XMLHttpRequest对象,考虑兼容性。 var getXmlHttp = function(){ var obj; if (window.XMLHttpRequest) obj = new XMLHttpRequest(); else obj = new ActiveXObject("Microsoft.XMLHTTP"); return obj; }; //采用Http请求get方式;open()方法的第三个参数表示采用异步(true)还是同步(false)处理 var xmlHttp = getXmlHttp(); xmlHttp.open("GET", "http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js", true); xmlHttp.send(); xmlHttp.onreadystatechange = function(){ if (xmlHttp.readyState == 4 && xmlHttp.status == 200){ eval(xmlHttp.responseText); //alert($);//可以弹出$,表明JS已经加载进来。click事件放在其它出会出问题,应该是还没加载进来 $("#btn1").click(function(){ alert($(this).text()); }); } }

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

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwzygs.html