Async v.s. defer

In the What is JavaScript tutorial, it says:

Async scripts will download the script without blocking rendering the page and will execute it as soon as the script finishes downloading. You get no guarantee that scripts will run in any specific order, only that they will not stop the rest of the page from displaying. It is best to use async when the scripts in the page run independently from each other and depend on no other script on the page.

I am not sure what script that I outlined in bold means. Does they mean the JavaScripts inside <script>, or any scripts within the document (including HTML and CSS)?
I feel like it is talking about the later. But if that is the case, I am confused. If there is no HTML, what can the JavaScripts operate on?

And if it does mean the later, just to be clear, are the below understandings correct?

  • async: The browser loads whatever HTML, CSS, and other JavaScript are in the .html file while it is downloading the external .js file with async, and loads the .js file once they finish downloading.
  • defer: The browser loads whatever HTML, CSS, and other JavaScript are in the .html file while it is downloading the external .js file with defer. But it only loads the .js file after the rest HTML, CSS, other JavaScripts without defer, and other JavaScripts with defer that goes before the current JavaScript is loaded.

Hi @saralin10co! I had a look at this page, and the way it was is a little confusing; I updated it to hopefully make things better. Also read the section before " async and defer", to give more context as to how you’d use defer. You’ll probably use defer a lot more than async.

To give you some answers:

  1. async and defer can only be used on scripts loaded form external script files, e.g. <script src="myscript.js">. They can’t be used on scripts inside the page, e.g. <script> ...some script ... </script>.

  2. The way I understand it, async and defer both instruct the browser to download the script(s) in a separate thread, while the rest of the page (the DOM, etc.) is downloading…so the page loading is not blocked by the scripts. The difference is that the async scripts will run as soon as they are available, in whatever order they download, whereas the defer scripts will not run until the page has finished loading, and will run in the order they appear on the page.

So the use case for async scripts is that you just want the scripts to load and run as soon as possible, but not block the page loading, and the scripts don’t depend on the content of the page (they might be data files for a game, for example - you want them to load in the background while the UI is also loading and the player is being given information, but they don’t rely on the DOM being available)

The use case for defer scripts is that you want the script to load efficiently, but you want it to not run until the DOM has loaded because it relies on the DOM content being there (and will error if it is not there yet when it runs).

Does that make sense? Do I need to rewrite that bit further to make it less confusing?

1 Like

Thanks a lot. I think I’ve got it! Basically, both of them don’t stop the rest of the .html content loading while they are downloading their external content. The difference is that with async, the downloaded external content starts executing the once the download is complete. And with defer, the downloaded external contents are executed after the rest of the page has finished loading and in the order they appear in the .html. Right?

If yes, then I think your answer here is quite clear!

Do you mean here or the original tutorial? The original tutorial still is a bit confusing to me… I think because it wasn’t clear at first that there are two steps with the external JavaScript (downloading it and loading it). So for example, in the section before “async and defer”, one description on defer confused me:

In this case both the script and the HTML will load simultaneously and the code will work.

Now that I know there are two steps, it makes sense. But when I read it at first it was confusing.

Yup, that’s right. This is an improvement over old-school JS loading, because JS used to be blocking when loaded like this — if you had a huge chunk of JS loading in at the stary of your page, it would block everything until it downloaded.

The difference is that with async , the downloaded external content starts executing the once the download is complete. And with defer , the downloaded external contents are executed after the rest of the page has finished loading and in the order they appear in the .html. Right?

Bingo!

Do you mean here or the original tutorial?

Yup, I meant the original tutorial. I am going to take on board what you’ve said here and try to make it less confusing for future readers. Thanks for the input — this has been super helpful.

Thank you for answering all my questions!

This explains it succinctly. I also like to think about them literally: what the words async and defer means, and in relation to the browser running them.

The difference is in when the browser runs the script(s). In both cases, the browser will automatically download the scrips and hold on to them. Then it does this:

  1. With defer, the execution of scripts are “deferred” until after the DOM is parsed, just before it is rendered (DOMContentLoaded is true).
  2. With async, the execution of scripts are done as soon they are available for execution.

The points above is why you should not depend on async if:

  1. It changes something in the DOM
  2. Multiple async scripts depends on each other because there’s no sequential guarantee.

Also, the HTML5 spec indicates that deferred scripts will be executed in the order they appear and before DOMContentLoaded, but this isn’t always the case, in reality, so it’s best to include just one when possible - as with async scripts also.

See the spec