The async attribute in script
async is a <script> attribute that tells the browser to download the script asynchronously, in parallel with the HTML, and to execute it right after it arrives, without waiting for the DOM to be built or for other scripts. It is the fastest but also the least predictable way to include a script, because the execution order of the files is not guaranteed.
Theory
TL;DR
asyncdownloads an external script in parallel with HTML parsing, and parsing is not stopped for the download.- As soon as the file has arrived it runs immediately, even if the HTML has not been fully read yet.
- That execution can briefly interrupt the parsing of the page.
- The order of several
asyncscripts is arbitrary and depends on network speed. asyncanddeferonly apply to external scripts withsrc; inline scripts ignore them.- Use
asyncfor independent code (analytics, ads, widgets) anddeferfor the main site logic.
Quick example
<head>
<!-- independent script: downloads in the background and starts as soon as it is ready -->
<script src="analytics.js" async></script>
</head>How a plain <script> works
<script src="app.js"></script>What the browser does:
- Starts reading the HTML.
- Meets a
<script>. - Stops parsing the HTML.
- Downloads
app.js. - Executes
app.js. - Continues reading the HTML.
So a plain <script> blocks page loading until it has been executed.
What async does
<script src="app.js" async></script>Now:
- The browser keeps loading the HTML.
- In parallel it downloads
app.jsin the background. - As soon as
app.jshas arrived, it executes it immediately, even if the HTML is not finished.
That is:
- the download is asynchronous;
- the execution is immediate;
- the order relative to other scripts is not guaranteed.
Visually it looks like this:
HTML: |-----parsing-----|-------->
JS: |---download---|execution|HTML and JS are fetched in parallel, but JS execution can interrupt HTML parsing if the script finishes downloading first.
How it differs from defer
| Attribute | When the script runs | Order | Blocks HTML | When to use |
|---|---|---|---|---|
| (no attribute) | Immediately when met | In order | Yes | Legacy inline code |
async | Right after download | Random | May interrupt | Independent scripts (analytics, ads) |
defer | After the DOM is built | In order | No | The main site code |
The gist:
asyncmeans "run when you are ready, wait for nobody";defermeans "wait until the DOM is built, then run in order".
A combined property table:
| Property | async | defer |
|---|---|---|
| Downloads in parallel with HTML | Yes | Yes |
| Runs as soon as it is downloaded | Yes | No |
| Waits for the DOM to be ready | No | Yes |
| Preserves script order | No | Yes |
| Blocks HTML parsing while executing | Yes, it may interrupt | No |
| Ideal for | Independent scripts (analytics, ads, widgets) | The main site logic |
Several async scripts
<script src="a.js" async></script>
<script src="b.js" async></script>They may execute in any order, depending on which file downloads first. So if b.js counts on globals defined by a.js, that pair will break sooner or later on a slow network.
There is another consequence: an async script can start before the markup element it needs exists. If the code touches the DOM, either switch to defer or wrap the work in a DOMContentLoaded handler.
Correct usage in <head>
async and defer work only for external scripts (src="..."). Inline ones (<script>...</script>) ignore these attributes.
An example of correct inclusion:
<head>
<script src="vendor.js" async></script>
<script src="main.js" defer></script>
</head>Here the analytics-like vendor.js is independent and can start at once, while main.js depends on the DOM and therefore runs after it has been built.
An easy way to remember:
asyncmeans "download and run as fast as possible",defermeans "download early, but wait until the DOM is ready".
Common mistakes
- Putting
asyncon scripts that depend on each other. The order is random and the dependency will break unexpectedly. - Touching the DOM from an
asyncscript. The element you need may not exist yet; usedeferor wait forDOMContentLoaded. - Writing
asyncon an inline script. Withoutsrcthe attribute has no effect at all. - Assuming
asyncnever blocks the page. The download does not block, but the execution can interrupt HTML parsing. - Putting
asyncon the main application bundle. It almost always depends on the DOM and on order, which is a job fordefer. - Expecting
DOMContentLoadedto wait for anasyncscript. The event may fire before such a file has even downloaded.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.