Is the "async" attribute/property useful if a script is dynamically added to the DOM?
The question is does s.async = true
have a use for dynamically inserted scripts, or are these loaded asynchronously already. The answer is they aren't loaded asynchronously in all browsers, as explained here (thanks to Markus Olsson for the link)
script-inserted scripts execute asynchronously in IE and WebKit, but synchronously in Opera and pre-4.0 Firefox. In Firefox 4.0, the async DOM property defaults to true for script-created scripts, so the default behavior matches the behavior of IE and WebKit.
In browsers that support async
but don't already default to asynchronous loading (for example, Firefox 3.6), async = true
makes a difference.
(The above link confirms that async is supported in Gecko 1.9.2, the layout engine used by Firefox 3.6)
The specification (now) dictates that a script
element that isn't parser-inserted is async; the async
property is irrelevant to non-parser-inserted script
elements:
The third is a flag indicating whether the element will "force-async". Initially,
script
elements must have this flag set. It is unset by the HTML parser and the XML parser onscript
elements they insert. In addition, whenever a script element whose "force-async" flag is set has aasync
content attribute added, the element's "force-async" flag must be unset.
Having the async
content attribute does, of course, mean the script would be executed asynchronously. The spec language seems to leave an opportunity to force synchronous execution of the script (by setting the attribute and then removing it), but in practice that does not work and is probably just a bit of vagueness in the spec. Non-parser-inserted script
elements are async.
This specified behavior is what IE and Chrome have always done, Firefox has done for years, and current Opera also does (I have no idea when it changed from the old behavior in the answer linked above).
It's easily tested:
var script = document.createElement("script");
script.src = "script.js";
console.log("a");
document.body.appendChild(script);
console.log("b");
...with script.js
being
console.log("script loaded");
...will log
a b script loaded
Interesting - I think it turns out that I was wrong in my assumptions.
Based on this thread in the jQuery developers' forum:
http://forum.jquery.com/topic/jquery-ajax-async-vs-html5-script-async
it looks like the async
property has been discovered to have an effect on dynamically-appended scripts, at least in Firefox (and potentially Opera, though it doesn't yet support the property).
The forum thread also cites Google's asynchronous tracking code implementation, which, although it appears to make use of the async
property in the appropriate context, actually appears to get the syntax wrong. Google uses:
ga.async = true;
when apparently that doesn't work; the proper method would be to use either:
ga.async = 'async';
or
ga.setAttribute('async', 'async');
So, based on my current understanding, not all browsers will actually execute dynamically-appended scripts immediately upon their insertion into the DOM in all cases; Firefox (and eventually Opera) will need the async
property to be set to ensure that this always happens.
More info on Firefox's implementation of async
here:
https://bugzilla.mozilla.org/show_bug.cgi?id=503481