Async & Defer
Open the project folder
In our starter files, open the index.html page from this lessons folder:
01.JavaScript Basics > 02.Async & Defer
In the previous lesson we discovered a problem when loading up JavaScript too early, before the HTML has finished loading.
This causes some problems:
- Using JavaScript, we may need to access a HTML element before it is created.
- We may have a lot of JavaScript to load which will slow down the page load time.
Opening the browser console will show the following error:
Uncaught TypeError: Cannot set properties of null (setting 'innerText')
This is because a HTML document is loaded in order from top to bottom, so the script
in the head
is loaded before it even knows the title
element exists, causing the error.
This lesson covers 2 ways of dealing with this, called async
and defer
. These are added as an attribute to our opening script
tag:
// Using async:
<script defer src="script1.js"></script>
// Using defer:
<script defer src="script1.js"></script>
Give this a try, using either of these options will clear the console error and apply the JavaScript to the title element. So, both of these work, but what are they, and what is the difference?
Async
First, we have async, async
is short for asynchronous and this is a subject we will cover in more detail soon.
But for this case, async
will download the script alongside the rest of the HTML content, without blocking the page from displaying, then run the script as soon as it has finished downloading.
This is useful since it does not block loading, but there is a drawback which means the scripts are not always loaded in the correct order. To see this, we need to create two more script files:
Create files script2.js
and script3.js
alongside our current script1.js
file.
Your folder directory should now look like this:
Modify contents of the three script files as follows:
// script1.js
console.log(1);
// script2.js
console.log(2);
// script3.js
console.log(3);
A console.log();
is a method to display output in the browser console, here we add the output as a number to represent each file.
Then link these addition script files in the head
section of the index.html
file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Async & defer</title>
<script async src="script1.js"></script>
<!-- Link 2x scripts -->
<script async src="script2.js"></script>
<script async src="script3.js"></script>
</head>
<body>
<h1 id="title">Where to add JavaScript</h1>
</body>
</html>
Over to the browser console, and in theory we should see the console log's in numerical order:
1
2
3
But, this is not always the case. If we continue to refresh the browser we may see another order:
1
3
2
This may take many attempts but this is something which can happen when the scripts are loaded async
. We are requesting all three scripts in order, but it does not mean they will always come back in the same order.
Why should we care about this?
Consider some CSS and JavaScript frameworks or libraries we can use as developers, such as the popular Bootstrap framework.
Ofter these frameworks have multiple scripts to import. The order of loading can be important if one file relies on code in an earlier file to function correctly.
Using async
here may cause problems, this is why some frameworks or libraries will recommend linking to scripts at the bottom of the body
section, as we looked at in the last lesson.
This means things work correctly, but it still has to wait on the HTML content loading first.
Defer
We also have defer
. These scripts are downloaded along with the rest of the page content, only then they will excecute in the source order:
<script defer src="script1.js"></script>
<script defer src="script2.js"></script>
<script defer src="script3.js"></script>
Changing this will now always see our console log's render in order.
Recap
Async:
- Will download the script alongside the rest of the HTML content.
- The browser will attempt to render the page while downloading.
- Runs the script as soon as it has finished downloading.
- No guarantee the scripts will run in order
Useful to use with multiple scripts which do not depend on eachother.
Defer:
- Will load multiple scripts in order.
- Does not bloc page content from rendering.
- Scripts will run as soon as both the page content, and scripts have finished downloading.
Useful to use with multiple scripts that need to run in order.