手机版

浏览器环境中JavaScript脚本加载和执行分析动态脚本和Ajax脚本注入

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

在《浏览器环境下JavaScript脚本加载与执行探析之defer与async特性》中,我们研究了延迟脚本(delayed)和异步脚本(async)的执行时机、浏览器支持、浏览器bug等细节。除了延迟和异步特性之外,动态脚本和Ajax脚本注入是创建非阻塞脚本的两种常用方法。一般来说,这两种方法都可以实现脚本加载不影响页面解析和渲染的功能,但是在不同的浏览器中,这两种技术创建的脚本的执行时机还是不同的。今天,我们将讨论动态脚本技术和Ajax在这些方面注入的脚本的特性。

代码准备:

我们使用《浏览器环境下JavaScript脚本加载与执行探析之代码执行顺序》第2.3节中的loadScript函数来添加动态脚本,并使用本文第2.4节中的loadXhrScript函数来实现Ajax脚本注入。我们将这两个函数都放在了util.js中

另外,本文使用的CHROME版本为47.0.2526.80,firefox版本为43.0.4,opera版本为30.0.1835.125。

1动态脚本。

1.1动态脚本的执行时机。

在《浏览器环境下JavaScript脚本加载与执行探析之defer与async特性》第2.3节DEMO的基础上,我们增加了三个外部js文件:

dynamic1.js

Test='我是head的外部动态脚本\ n ';

dynamic2.js

Test='我是body的外部动态脚本\ n ';

dynamic3.js

Test='我是底层外部动态脚本\ n ';

1.1.1 DEMO1:动态脚本执行时机的初步研究。

超文本标记语言的代码是:

!DOCTYPE htmlhtmlhearteta charset=' UTF-'/title dynamic Script Test/title Script src=' http :http://lib . sinapp.com/js/jquery/./jquery-.min . js '/script script src=' http : util . js '/script script type=' text/JavaScript ' var test=' ';/scriptscriptloadScript(' dynamic . js ');/scriptscripttest='我是头部内部脚本\ n ';/script script src=' http : js ' type=' text/JavaScript '/script/headsdybuttonid=' test ' click/buttonscriptloadscript(' dynamic . js ');/script script src=' http : js ' type=' text/JavaScript '/script/bodyscriptloadScript(' dynamic . js ');/script script src=' http : js ' type=' text/JavaScript '/script script $(function(){ test='我是DOMContentLoaded中的脚本\ n ';})window . onload=function(){ test='我是window.onload \n中的脚本';var button=document . getelementbyid(' test ');button . onclick=function(){ console . log(test);}}/script在代码中,我们在HTML的head标签中添加了三个动态脚本文件,同时对比了正常的外部脚本和内部脚本的执行情况,我们来看看不同浏览器中的执行结果:

注意:火狐和opera中的执行结果可能会改变。

从上面的例子中,我们可以看到动态脚本的执行时间在不同的浏览器中有很大的不同,但是以下两点是清楚的:

[1]动态脚本确实可以起到不阻塞后续脚本的作用,即延迟,但这种延迟作用可能不会持续到所有正常脚本执行完毕,也不能保证延迟到DOMContentLoaded之后。

[2]动态脚本执行的顺序无法保证,本文//www . JB 51 . net/article/77920 . htm及后续几篇文章对此进行了详细说明。

从这个DEMO中也可以看出,动态脚本的执行时机是不确定的。虽然在DEMO1中,动态脚本是在DOMContentLoaded事件之后执行的,但这并不意味着动态脚本不会阻止DOMContentLoaded。让我们通过DEOM2来看一下:

1.1.2 DEMO2:动态脚本加载的DOMContentLoaded的阻塞。

我们将DEMO1第27行的代码修改为:

脚本src='http:/delayfile.php?URL=http://localhost/js/load/3.jsdelay=5 ' type=' text/JavaScript '/script我们使用《浏览器环境下JavaScript脚本加载与执行探析之代码执行顺序》中的delayfile.php将3 . js的返回延迟5秒。我们知道,如果是延迟脚本,无论正常外部脚本延迟多长时间,延迟脚本在正常外部脚本之后仍然会执行,而动态脚本不会。让我们看看浏览器中修改后的代码的执行顺序:

注意:火狐和opera中的执行结果可能会改变。

可以看到,当一个正常的脚本长时间加载时,动态脚本的执行明显提前,在IE、CHROME、firefox和opera中是在DOMContentLoaded之前执行的。所以我们可以初步判断,动态脚本的执行时机是不确定的,在不同的浏览器中是不一样的,但一般来说应该是在代码加载之后,JavaScript代码在线程中执行没有一定的时间,但是不同的浏览器有不同的时间。

因此,不确定动态脚本是否会阻止DOMContentLoaded,因为动态脚本可能会在触发DOMContentLoaded之前或之后执行。而且,由于IE=8不支持真实的DOMContentLoaded事件,jQuery也模拟判断了IE=8中该事件的发生(下一篇文章将具体讲解DOMContentLoaded事件),这也会在一定程度上影响上述代码的执行结果。

1.1.3 DEMO3:动态脚本和延期。

我们知道,defer脚本有一个相对明确的执行机会,即在页面解析完成后,在DOMContentLoaded触发器之前加载并执行。事实上,它们在执行机会上没有相关性。但是,在实际实验中,发现动态脚本可以在延期脚本之前或之后执行,但不会中断延期脚本的执行。我们将在《浏览器环境下JavaScript脚本加载与执行探析之defer与async特性》第2.3节的DEMO中介绍延迟脚本,并对HTML代码进行如下修改。

!DOCTYPE htmlhtmlhearteta charset=' UTF-'/title dynamic Script Test/title Script src=' http :http://lib . sinapp.com/js/jquery/./jquery-.min . js '/Script src=' http : util . js '/Script Script $(function(){ test='我是DOMContentLoaded中的脚本\ n ';})window . onload=function(){ test='我是window.onload \n中的脚本';var button=document . getelementbyid(' test ');button . onclick=function(){ console . log(test);} }/script script type=' text/JavaScript ' var test=';/scriptscriptloadScript(' dynamic . js ');/scriptscripttest='我是头部内部脚本\ n ';/script script src=' http : defer . js ' type=' text/JavaScript ' delay=' delay '/script script src=' http : js ' type=' text/JavaScript '/script/Headybutton id=' test ' click/button script loadscript(' dynamic . js ');/script script src=' http : defer . js ' type=' text/JavaScript ' delay=' delay '/script script src=' http : js ' type=' text/JavaScript '/script/bodyscriptloadScript(' dynamic . js ');/script script src=' http : defer . js ' type=' text/JavaScript ' delay=' delay '/script script src=' http : js ' type=' text/JavaScript '/script/html注意:firefox和opera中的执行结果可能会发生变化。

我们添加了几个defer脚本,然后我们将在不同的浏览器中查看执行结果:

从实验结果可以看出,动态脚本的执行时机与延迟脚本没有直接关系。表面上看,在CHROME和firefox中,延迟脚本总是在动态脚本之前执行。《前端优化-Javascript篇(2.异步加载脚本)》中提到“ScriptDOM和defer可以同时执行,在不同的浏览器中优先级不同。在Firfox和Chrome中,ScriptDOM的优先级低于defer,而在IE中,情况正好相反。”事实上,这种优先权不应该存在。我们只需要给延迟脚本添加一个加载延迟,然后动态脚本将在延迟脚本之前执行。

1.2动态脚本执行问题总结。

让我们总结一下动态脚本的执行:

[1]首先,动态脚本可以在一定程度上延迟脚本的执行,但由于动态脚本执行时机的不确定性,这种延迟的效果是未知的。

[2]其次,动态脚本的执行顺序可能不是加法的顺序,这是动态脚本技术的大问题之一。最简单的解决方法是使用回调函数监控脚本的加载状态,然后在加载一个脚本后动态添加下一个脚本。

[3]动态脚本没有确切的执行时间。当脚本元素通过方法添加到DOM中时,比如DOM的appendChild和insertBefore,JS脚本将被加载。脚本的执行应该是在加载后的某个时间,不同的浏览器对这个时间的处理有很大的差异。比如在IE中,应该采用尽快执行的策略,即加载后寻找机会尽快执行代码。

[4]动态脚本可能在DOMContentLoaded触发器之前或之后执行,因此无法确定它是否会阻止DOMContentLoaded。在正常情况下,动态脚本会阻塞window.onload,但也有动态脚本会在window.onload被触发后执行,这样window.onload就不会被阻塞。

2 Ajax注入脚本。

2.1 Ajax注入脚本的时机。

Ajax脚本注入技术有两种模式:同步加载和异步加载。同步加载相对简单,脚本的加载和执行会阻塞后续代码的执行,直到注入的代码被加载和执行。我们主要讨论异步模式下的情况:

2 . 1 . 1 demo 4:Ajax注入脚本的实现。

我们再添加三个外部文件:

ajax1.js

Test='我是头外部AJAX脚本\ n ';

ajax2.js

Test='我是体外的AJAX脚本\ n ';

ajax3.js

Test='我是底层外部AJAX脚本\ n ';

超文本标记语言的代码是:

!DOCTYPE htmlhtmlhearteta charset=' UTF-'/title AJax Script Test/title Script src=' http :http://lib . sinapp.com/js/jquery/./jquery-.min . js '/script script src=' http : util . js '/script script type=' text/JavaScript ' var test=' ';/script script $(function(){ test='我是DOMContentLoaded中的脚本\ n ';})window . onload=function(){ test='我是window.onload \n中的脚本';var button=document . getelementbyid(' test ');button . onclick=function(){ console . log(test);} }/scriptscriptloadXhrScript(' Ajax . js ',true);/scriptscripttest='我是头部内部脚本\ n ';/script script src=' http : js ' type=' text/JavaScript '/script/headsdybuttonid=' test ' click/buttonscriptloadxhrscript(' Ajax . js ',true);/script script src=' http : js ' type=' text/JavaScript '/script/bodyscriptloadXhrScript(' Ajax . js ',true);/script script src=' http : js ' type=' text/JavaScript '/script/html在这段代码中,我们分别在head标记内部、body标记内部和body标记外部添加了三个注入脚本。以通常介绍的脚本为参考,让我们看看浏览器中的执行结果:

注意:火狐、opera、IE中的执行结果可能会有变化。

从这个执行结果可以看出,Ajax注入脚本的执行时机更加不确定。事实上,与动态脚本类似,Ajax注入脚本的加载过程是异步的。因此,装载时间一开始是不确定的。其次,脚本加载后浏览器何时执行加载的代码也是不确定的。我们将异步模式下Ajax注入脚本的执行时间总结如下:

[1]Ajax注入的脚本也有一定的延迟,但和动态脚本一样,延迟时间是不确定的。

[2]Ajax注入脚本的执行顺序出了问题。虽然DEMO4中的示例看起来所有注入的脚本都是按照加法的顺序执行的,但是如果稍微理解一下异步和动态脚本的执行顺序,我们应该能够理解这一点。

[3]Ajax注入脚本的执行时机也是不确定的,这与脚本的加载时间和浏览器的处理机制有关。

[4]由于以上几点,Ajax注入的脚本可能会阻塞DOMContentLoaded或window.onload。

版权声明:浏览器环境中JavaScript脚本加载和执行分析动态脚本和Ajax脚本注入是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。

相关文章推荐