宝哥软件园

异步加载JavaScript概述

编辑:宝哥软件园 来源:互联网 时间:2021-09-01

同步加载的问题

默认的js是同步加载的,这里的“加载”可以理解为解析和执行,而不是下载。在最新版本的浏览器中,代码请求的资源是以瀑布的方式加载的,而不是阻塞的,但是js的执行总是被阻塞的。这会造成什么问题?如果我的索引页需要加载一些js,但是其中一个请求被延迟了,那么下面的JS代码的执行就会被阻塞(同步加载),页面呈现就无法继续(如果在head标签之后引入JS)。

脚本类型=' text/JavaScript ' src=' http://China-addthis . googlecode.com/SVN/trunk/addthis . js '/script script type=' text/JavaScript ' src=' http://libs.baidu.com/jquery/2.0.0/jquery.min.js'/script这是一个测试。例如,上面的代码保存为index.html文件,页面的主体是一个简单的字符串,但是代码执行后页面总是空白的。为什么呢?因为请求的js长时间无法加载(可能是Google被屏蔽等原因)。),以下代码的执行被阻止,页面无法呈现。也许你会建议你可以在把js代码放入/body之前渲染页面!好办法,让我们试着把js抛在脑后:

这是一个test script type=' text/JavaScript ' src=' http://China-addthis . googlecode.com/SVN/trunk/addthis . js '/script script type=' text/JavaScript ' src=' http://libs.baidu.com/jquery/2.0.0/jquery.min.js'/script页面瞬间被渲染出来,“这是一个测试”很快出现在前景中,世界看似平静,但:

这是一个testscript类型=' text/JavaScript ' src=' http://China-addthis . googlecode.com/SVN/trunk/addthis . js '/script script type=' text/JavaScript ' src=' http://libs . Baidu.com/jquery/2 . 0 . 0/jquery . min . js '/script script type=' text/JavaScript ' console . log(' hello world ');/script只是在前面代码的基础上增加了一段代码,但是‘hello world’很长时间都无法在控制台上输出。显然,前面的js请求阻止了下面代码的加载。我们恍然大悟,改变js的加载位置只能改变页面呈现。但是,js加载没有任何用处,js仍然会阻塞。

实现js异步加载

我们的需求似乎非常简单,我们可以在加载页面的同时在控制台上输出字符串。说得通俗一点,我们应该在第一段请求Google提供的js的同时,继续执行下面的js,也就是实现js的异步加载。

最常见的方法是动态生成脚本标签:

body这是一个测试脚本类型=' text/JavaScript ' ~ function(){ var s=document . createelement(' script ');s . src=' http://China-addthis . googlecode.com/SVN/trunk/addthis . js ';document . body . appendchild;}();/script script type=' text/JavaScript ' src=' http://libs . Baidu.com/jquery/2 . 0 . 0/jquery . min . js '/script script type=' text/JavaScript ' console . log(' hello world ');/剧本/正文,但还是有些问题。此加载方法将防止在加载完成前触发onload事件。现在,许多页面代码必须在onload期间执行额外的渲染工作,因此它仍然会阻止某些页面的初始化处理:

body这是一个测试脚本类型=' text/JavaScript ' ~ function(){//function async _ load(){ var s=document . createelement(' script ');s . src=' http://China-addthis . googlecode.com/SVN/trunk/addthis . js ';document . body . appendchild;//}//window . addeventlistener(' load ',async_load,false);}();window . onload=function(){ var txt=document . createtextnode(' hello world ');document . body . appendchild(txt);};/script script type=' text/JavaScript ' src=' http://libs . Baidu.com/jquery/2 . 0 . 0/jquery . min . js '/script/body。例如,上面的代码不能很好地呈现“hello world”,所以我们只需要移除注释,让Google提供的js在onload时异步开始加载。这解决了阻塞onload事件触发的问题。

补充domContentLoaded和OnLoad事件DOMContentLoaded :页面(文档)已经解析,页面中的DOM元素可用。但是,页面中引用的图片和子帧可能尚未加载。加载:页面的所有资源都已加载(包括图片)。此时浏览器的加载进度停止。这两个时间点将页面加载的时间线分为三个阶段。

以上似乎更好地解决了这个问题,但是html5提供了一个更简单的方法,async属性!

这是一个test script type=' text/JavaScript ' src=' http://China-addthis . googlecode.com/SVN/trunk/addthis . js ' async=' async '/script script type=' text/JavaScript ' src=' http://libs . Baidu.com/jquery/2 . 0 . 0/jquery . min . js '/script script type=' text/JavaScript ' console . log(' hello world ');/scriptasync是html5的一个新属性。async属性规定,一旦脚本可用,它将异步执行(一旦下载,它将立即执行)。

应当注意,异步属性仅适用于外部脚本(仅当使用src属性时)

“延迟”属性经常与async一起提及:

这是一个test script type=' text/JavaScript ' src=' http://China-addthis . googlecode.com/SVN/trunk/addthis . js ' delay=' delay '/script script type=' text/JavaScript ' src=' http://libs . Baidu.com/jquery/2 . 0 . 0/jquery . min . js '/script script type=' text/JavaScript ' console . log(' hello world ');/剧本看似达到了同样的效果,但真的一样吗?让我们看看defer属性的定义。

在过去,defender只支持ie的hack,但是现在html5的出现已经完全支持defender了。defer属性指定在页面完成加载之前不会执行脚本。“延迟”属性仅适用于外部脚本(仅在使用src属性时)。PS:ie支持的delay好像不是这样的,因为我对IE不感兴趣,也不深入。如果有兴趣,可以查阅相关资料。

既然异步和延迟经常一起出现,那就区分它们吧!

如果没有异步和延迟属性(赋值为真,下同),那么浏览器会立即执行当前的js脚本,并阻塞下面的脚本;如果有async属性,加载和渲染后续文档元素的过程将与当前js的加载和执行并行进行(异步);如果有defer属性,加载后续文档元素的过程将与script.js的加载并行(异步),但是script.js的执行将在解析所有元素(DOM)之后并在触发DOMContentLoaded事件之前完成。

我们来看一张网上盗窃的图片:

蓝线代表网络阅读,红线代表执行时间,两者都是针对脚本的;绿线代表HTML解析。

该图告诉我们以下要点(从延迟和异步的区别中提取):

延迟和异步在网络读取(下载)中是相同的,并且两者都是异步的(与HTML解析相比)。两者的区别在于下载后脚本执行的时间。显然,defer最接近我们对应用程序脚本加载和执行的要求。这个图没有涉及的是它根据加载顺序执行脚本。好好利用这一点。async是无序执行的大师。反正脚本的加载和执行都和它息息相关,所以不管你声明什么顺序,只要加载了就会立即执行。仔细想想,async对应用程序脚本来说用处不大,因为它根本不考虑依赖性(即使是最低级的执行)。但是,它非常适合不依赖于任何脚本或者不依赖于任何脚本的脚本。最典型的例子是Google Analytics,但在我看来(以下个人理解,如有出入,请指出),异步加载中的defer应用不会比异步更广。Async的英文解释是异步的。该属性作用于脚本,使脚本在加载(下载)后立即执行,类似于动态插入脚本标签(async只支持h5,与浏览器兼容);延迟的英文解释是delay,类似于字面解释。延迟脚本的执行使得dom元素在加载后开始有序地执行脚本。因为它是有序的,它会带来另一个问题:

这是一个测试脚本类型=' text/JavaScript ' src=' http://China-addthis。谷歌代码。com/SVN/trunk/addthis。js ' delay=' delay '/script脚本类型=' text/JavaScript ' src=' http://libs。百度。com/jquery/2。0 .0/jquery。量滴js ' delay=' delay '/script脚本类型=' text/JavaScript ' src=' index。js ' delay=.如果执行这段代码,控制台的《你好世界》也会迟迟得不到结果。所以我觉得还是异步非同步(异步)好用,如果要考虑依赖的话,可以选择requirejs、seajs等模块加载器。

总结

JavaScript的异步加载还有一些方式,比如:AJAX eval(使用创建交互式、快速动态网页应用的网页开发技术得到脚本内容,然后通过eval(xmlhttp.responseText)来运行脚本)、iframe方式等。

以上理解如果有出入,还望指出~感谢大家对我们的支持。

更多资讯
游戏推荐
更多+