Script 元素的异步加载属性
进入正题之前,先考大家一个问题:defer 属性现在有哪些浏览器支持?
喜悦
除了 defer 属性,script 还新增了一个 async 属性,请看 MDC:
async Requires Gecko 1.9.2
This Boolean attribute is set to indicate that the browser should, if possible, execute the script asynchronously. If the script cannot be executed asynchronously, or the browser doesn’t support this attribute, the script is executed synchronously (and loading the content blocks until the script finishes running).
理想情况下,利用 async 属性,脚本异步加载将变得非常简单:
async-test.js:
var g = 1;
async-test-1.html:
<script src="async-test.js" async="true"></script> <script> alert(typeof g); // Firefox 3.6 弹出 undefined </script>
测试页面:async-test-1.html
目前只有 Firefox 3.6 支持 async 属性,希望其它浏览器能迅速跟进。
悲哀
Firefox 3.6 的尝试和探索精神令人钦佩。但是,在引入这个新特性时,也导致了传统异步加载方式的失效:
<script> (function(d) { var a = d.createElement('script'); a.src = 'async-test.js'; d.getElementsByTagName('head')[0].appendChild(a); })(document); </script> <script> alert(typeof g); // 预期结果是 undefined, Firefox 3.6 弹出 number </script>
测试页面:async-test-2.html
真糟糕!类似问题,还有 Steve Souders 前不久发现的 document.write 在 Firefox 3.6 下的阻塞行为。
分析
用 Firebug 可以看到,在 Firefox 3.6 中,script 元素 async 属性的默认值是 false. 换言之,script 元素默认是同步加载的。可以推测,Firefox 3.6 在增加 async 这个属性时,很可能忽略了用 createElement(’script’) 和 document.write(‘<script…’) 等方式创建的 script 元素,async 的属性值应该从默认值 false 调整为 true. 正是这个疏忽,导致了传统加载异步脚本的方式在 Firefox 3.6 中失效。对于 YUI3 和很多站点来说,这实在是太糟糕了。
知道了问题本因,可以得到目前异步加载脚本最安全的方式如下:
<script> (function(d) { var a = d.createElement('script'); a.async = true; a.src = 'async-test.js'; d.getElementsByTagName('head')[0].appendChild(a); })(document); </script>
测试页面:async-test-3.html
注意1:所有测试结果,均在无缓存的情况下得出。
注意2:async-test-2.html 和 async-test-3.html 在 Opera 10.10 中弹出值非预期,原因未深究,有兴趣者可以进一步挖掘。
感慨
Google 在 ga 的部署脚本 中已经使用上了 async 属性:
<script type="text/javascript"> (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'; (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(ga); })(); </script>
最后
再考大家一题,在 Firefox 3.6 下,下面的代码,alert 出什么:
<script src="async-test.js" async="false"></script> <script> alert(typeof g); // ? </script>
相关 [script 元素 异步] 推荐:
script的defer和async
- - 携程UED「学习笔记-Linux」学习Shell Script
- - CSDN博客系统运维推荐文章前端优化三续:用script存放html代码来减少DOM节点数
- - 博客园_旁观者逃走的元素
- Zoe - 玩意儿linux异步IO浅析
- Sepher - kouu's homeAndroid handler异步更新
- - 博客园_首页Android异步接口测试
- - 百度质量部 | 软件测试 | 测试技术 | 百度测试异步上传文件
- - Web前端 - ITeye博客上传头像: