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

IT技术 javascript asynchronous pageload page-load-time
2021-02-20 04:30:23

这个问题与哪些浏览器支持 <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 的书“甚至更快的网站”中的IIRC,它提示所有现代浏览器异步加载脚本(即,不阻止页面渲染或下载后续资产) .

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

4个回答

问题是s.async = true动态插入的脚本确实有用,或者这些脚本是否已经异步加载了。答案是,他们没有在所有的浏览器异步加载,如解释在这里(感谢马库斯·奥尔森的链接)

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

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

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

是否有“6 年后回来接受一直正确的答案,同时导致新接受的答案自相矛盾,因为它认为已接受的答案是错误的,当它刚刚成为正确答案时”的徽章本身?”
2021-05-04 04:30:23
关于最近浏览器版本的答案更新会很有趣。我目前使用s.setAttribute("async", "");. 你知道这是否有效吗?
2021-05-12 04:30:23

规范(现在)决定了一个script该元素并不解析器插入是异步; async属性与非解析器插入的script元素无关

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

async当然,拥有content 属性意味着脚本将异步执行。规范语言似乎留下了强制同步执行脚本的机会(通过设置属性然后删除它),但实际上这不起作用并且规范中可能只是有点模糊。非解析器插入的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");

...将记录

一个
脚本已加载

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

基于 jQuery 开发者论坛中的这个线程:

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

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

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

ga.async = true;

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

ga.async = 'async';

或者

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

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

有关 Firefox 实现的更多信息async

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

jQuery 论坛上非常有趣的主题。猜猜我的 google fu 不够强大,无法找到它 ;) 谢谢!
2021-04-20 04:30:23
我不认为这是正确的。 typeof ga.asyncis "boolean",即使在您将其设置为之后,'async'您也会发现 ga.async 的值为true(由于类型强制)。我在 FF 3.6 中检查了这个
2021-04-25 04:30:23
我相信说它在 jQuery 中不起作用的人误解了 async 属性应该做什么,正如其他一些海报指出的那样。顺便说一下,请注意ga.async = true结果类似于 HTML <script type="text/javascript" src="foo.js" async="">(至少在 Firebug 中查看),但据我所知,重要的是 async 属性的存在,而不是它后面的字符串。无论如何,ga.async = "async"结果是一样的。
2021-05-08 04:30:23
更正我的最后一条评论,显然如果在标记中为该async属性指定了一个值它应该是“async”或空字符串。但是当在 DOM 中设置它时(如在 中ga.async =) async 是一个布尔值,所以你应该将它设置为trueor false正如我所说,ga.async = "async"产生相同结果的事实只是因为"async"被强制转换为true.
2021-05-16 04:30:23

我相信你是对的。

史蒂夫自己的例子中,他没有在将脚本标签附加到 head 元素之前设置 async 属性。

我对async 属性的理解是,它是一种向浏览器发出信号的方式,表明您不打算通过使用 document.write 来操作页面,以便它可以继续呈现而不是停止加载脚本。请参阅mdc 上script 元素的文档,其中包含有关 document.write/async 问题的更多信息。

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

马库斯 - 很好的答案,我感谢你的贡献!我进一步研究了这一点,并做出了一些发现 - 请阅读我刚刚添加的答案。
2021-05-09 04:30:23