如果脚本动态添加到DOM,“async”属性/属性是否有用?

时间:2010-08-04 18:52:12

标签: javascript asynchronous pageload page-load-time

这个问题与Which browsers support <script async="async" />?相切。

我最近看到过一些类似这样的脚本:

var s = document.createElement('script');
s.type = 'text/javascript';
s.async = true;
s.src = 'http://www.example.com/script.js';
document.getElementsByTagName('head')[0].appendChild(s);

这是向DOM动态添加脚本的常用方法,来自Steve Souders的书籍“Even Faster Web Sites”的IIRC提示所有现代浏览器异步加载脚本(即不阻止页面呈现或下载)后续资产)。

如果我在这方面是正确的,s.async = true声明是否有用?即使对于支持该属性的浏览器,它也不是多余的,因为动态附加脚本应该已经触发异步下载吗?

4 个答案:

答案 0 :(得分:21)

问题是s.async = true是否可用于动态插入的脚本,或者是否已经异步加载这些脚本。答案是他们不是在所有浏览器中异步加载,如here所述(感谢Markus Olsson的链接)

脚本插入的脚本在IE和WebKit中异步执行,但在Opera和4.0之前的Firefox中同步执行。在Firefox 4.0中,对于脚本创建的脚本,async DOM属性默认为true,因此默认行为与IE和WebKit的行为相匹配。

在支持async但尚未默认为异步加载的浏览器中(例如,Firefox 3.6),async = true会有所作为。

(以上链接确认Gecko 1.9.2支持async,Firefox 3.6使用的布局引擎)

答案 1 :(得分:13)

answer accepted as of this writing已过期。 specification现在规定不是解析器插入的script元素是异步的; async属性与非解析器插入的script元素无关:

  

第三个是一个标志,指示该元素是否为“强制 - 异步”。最初,script元素必须设置此标志。 HTML解析器和它们插入的script元素上的XML解析器没有设置它。此外,每当设置了“ force-async ”标志的脚本元素添加了async内容属性时,元素的“ force-async ”标志必须没有设置。

拥有async内容属性当然意味着脚本将异步执行。规范语言似乎给机会强制同步执行脚本(通过设置属性然后删除它),但实际上这不起作用,可能只是有点模糊规范。非解析器插入的script元素是异步的。

此指定的行为是IE和Chrome一直以来所做的,Firefox已经做了多年,当前的Opera也做了(我不知道它何时从上面链接的答案中的旧行为改变了。)

很容易测试:

var script = document.createElement("script");
script.src = "script.js";
console.log("a");
document.body.appendChild(script);
console.log("b");

... script.js正在

console.log("script loaded");

...将记录

a
b
script loaded

答案 2 :(得分:2)

有趣 - 我认为事实证明我的假设是错误的。

基于jQuery开发人员论坛中的这个主题:

http://forum.jquery.com/topic/jquery-ajax-async-vs-html5-script-async

看起来async属性已被发现对动态附加脚本产生影响,至少在Firefox中(可能是Opera,虽然它还不支持该属性)。

论坛帖子还引用了Google的异步跟踪代码实现,尽管它似乎在适当的上下文中使用了async属性,但实际上似乎会出现错误的语法错误。 Google使用:

ga.async = true;

当显然不起作用时;正确的方法是使用:

ga.async = 'async';

ga.setAttribute('async', 'async');

因此,根据我目前的理解,并非所有浏览器在所有情况下都会在插入DOM后立即执行动态附加脚本; <(最终是Opera)需要设置async属性以确保始终发生这种情况。

有关Firefox async实施的更多信息:

https://bugzilla.mozilla.org/show_bug.cgi?id=503481

答案 3 :(得分:1)

我相信你是对的。

Steve's own examples中,在将脚本标记附加到head元素之前,他没有设置async属性。

我对async atttribute的理解是,它是一种向浏览器发出信号的方式,你不打算通过使用document.write来操作页面,这样它就可以继续渲染而不是停止加载脚本。请参阅script element at mdc的文档,其中包含有关document.write / async问题的更多信息。

请注意,使用您的技术,您无论如何都不应该使用document.write,因为您无法知道脚本在页面生命周期中的加载位置。