The HTML async attribute
The HTML async attribute runs a script as soon as it is available, even in the middle of parsing. With <script async src="analytics.js">, the parser never waits for the file. Async scripts run as each one finishes loading, and external scripts added with createElement() are async by default.
Overview
The HTML async attribute lets a script run once it is ready, without waiting for parsing to end. Classic <script> elements need a src for it to apply, while module scripts accept it with or without one.
Async scripts don't wait for parsing to finish or for each other. Whichever finishes downloading first runs first, sometimes before the page is fully parsed. The DOMContentLoaded event doesn't wait for them, but the window load event does.
Every script element starts with an internal force async flag set to true, and the parser clears it on scripts in the page's markup. A script you make with document.createElement() keeps the flag, so its async property reads true with no attribute present.
On a module script, async changes when the code runs. A module normally waits for parsing to finish, the way a deferred script does. With async, it runs as soon as the module and every module it loads through import statements are ready.
Syntax
<script async src="analytics.js"></script>
<script type="module" async src="widget.js"></script>
Values
| Value |
|---|
| Lets the script run once downloaded, without waiting for parsing. |
Example
<p id="order" role="status"></p>
<button type="button" id="make">Create a script element</button>
<p><label><input type="checkbox" id="off"> Set its async property to false</label></p>
<p id="msg" role="status"></p>
<p>Press the button, then tick the box and press it again.</p>
<script>
const order = [];
function ran(name) {
order.push(name);
document.getElementById('order').textContent = 'Run order here: ' + order.join(', ') + '.';
}
ran('inline script');
document.addEventListener('DOMContentLoaded', function () {
ran('DOMContentLoaded');
});
const msg = document.getElementById('msg');
msg.textContent = 'The inline script tag reports async as ' + document.currentScript.async + '.';
document.getElementById('make').addEventListener('click', function () {
const script = document.createElement('script');
if (document.getElementById('off').checked) {
script.async = false;
}
const attr = script.hasAttribute('async') ? 'an' : 'no';
msg.textContent = 'A new script element reports async as ' + script.async + ', with ' + attr + ' async attribute.';
});
</script>
<script async src="data:text/javascript,ran('async')"></script>
Best practices
- Choose
asyncfor a standalone script, one that depends on no other script, such as an analytics tag. - Load a library and the code that calls it with defer instead. Two async scripts can run in either order, so a plugin might run before its library and throw an error.
- In an async script, check
document.readyStatebefore adding aDOMContentLoadedlistener. The event may have fired already, and the setup code may then never run. - Keep
document.write()out of async scripts. The call is ignored, and Chrome logs a warning about an asynchronously loaded script.























