引言
2.2、onload 时的异步加载
1、同步加载
<script src="http://domin1.com/script1.js"></script>
<script type="text/javascript">
console.log('hello world');
</script>
这段代码中,如果请求的 script1.js 加载时间过长(domin1 被墙等原因),浏览器就会停止后续的文件下载,渲染,代码执行,第二个<script>中的"hello world"也无法显示。以前的处理方法是把<script>放置于页面末尾的</body>之前,可以使页面先显示出来,但这也只是另页面渲染不被阻塞而已,对于本例中第二个<script>的JS执行所造成的阻塞是无能为力的。
2、异步加载
2.1、Script DOM Element 法
(function (){ var async_script = document.createElement('script'); async_script.type = "text/javascript"; async_script.src = "http://domin.com/script.js"; var x = document.getElementsByTagName("script")[0]; x.ParentNode.insertBefore( async_script, x); })();
但问题还是存在:这段代码在下载和执行完之前会阻止 onload 事件的触发,于是有了onload 时的异步加载。
2.2、onload 时的异步加载
(function() { function async_load(){ var as = document.createElement("script"); as.type = "text/javascript"; as.src = "http://domain1.com/script.js"; var x = document.getElementsByTagName("script")[0]; x.parentNode.insertBefore(s, x); } if (window.attachEvent) window.attachEvent('onload', async_load); else window.addEventListener('load', async_load, false); })();
2.3、async 和 defer 属性
//async属性: <script src="script1.js" async="async"></script> //defer属性: <script src="script2.js" defer="defer"></script>
async属性使加载和渲染后续文档元素的过程将和当前js的加载与执行并行进行(异步);defer属性使下载后续文档元素的过程将和 script.js 的下载并行进行(异步),但是 script.js 的执行要在所有元素(DOM)解析完成之后,DOMContentLoaded 事件触发之前完成。但async属性是HTML5新增的,使用时需注意兼容性问题。
此处盗了个图:
该图中,绿线为HTML解析,蓝线为脚本下载,红线为脚本执行。我们可以看出默认情况下也就是同步模式下,脚本的下载和执行会阻塞HTML解析;异步模式中的async和defer两个属性在下载时均为异步不影响HTML解析,在执行均阻塞HTML解析,但defer胜在它可以控制脚本执行的时间,保证页面先加载出之后再执行脚本。
3、总述
除defer外,浏览器在下载完 JS 的内容后就会立即对其解析和执行,不管是同步加载还是异步加载。