deferAnd async is a script label of two properties, used to control the download and execution of the script without blocking the parsing of the page document.
Before we introduce them, we need to look at the loading and rendering process of the page first:
1. The browser requests the server through the HTTP protocol, obtains the HMTL document and starts to parse from top to bottom, constructs the DOM;
2. In the process of building the DOM, if you encounter an out-of-the-box style declaration and script declaration, pause document resolution, create a new network connection, and start downloading style files and script files;
3. After downloading the style file, build the Cssdom; After the script file download is complete, explain and execute, then continue parsing the document build Dom
4. After parsing the document, associate and map the DOM and Cssdom, and finally render the view to the browser window
In this process, the download and execution of the script file is synchronized with the document parsing, that is, it will block the parsing of the document and, if not properly controlled, will have a certain degree of impact on the user experience.
So we need a clear understanding and use defer and async to control the execution of external scripts.
In development we can script declare two less common properties in: defer and async , the following explains their usage separately:
defer: Used to open a new thread download script file and make the script execute after the document parsing is complete.
async: HTML5 new property to download the script file asynchronously and to interpret the execution code immediately after the download.
In order to demonstrate the execution of the script, and to describe the role of these two properties, let's start by building a simple server:
, we create a app directory to place some simple Web resources and create a simple node server server.js with the following code:
varHTTP =require(' http ');varFS =require(' FS ');varTypemapping = {' HTML ':' text/html ',' JS ':' Text/javascript ',' CSS ':' Text/css ',' ico ':' Image/x-icon '};varGetresourceextension = function(req) { varurl = req.url;varLastindexofdot = Url.lastindexof ('. ');if(Lastindexofdot = = =-1)return "';returnUrl.substring (Lastindexofdot +1);};varRespondresourcetoclient = function(req, res) { //read the Reource and respond via ' pipe 'Fs.createreadstream (Req.url.replace (/^\//,"'). pipe (res);};varServer = Http.createserver ( function(req, res) {Console.log (' requesting URL: ', Req.url);varExtension = getresourceextension (req); Res.writehead ( $, {' Content-type ': Typemapping[extension]});varDelay = function(time) {SetTimeout ( function() {Respondresourcetoclient (req, res); }, Time | |0); };if(Extension = = =' HTML '|| Extension = = =' CSS ') {Delay (0); }Else if(Extension = = =' JS ') {Delay ( +); }Else{Res.end ("'); }}); Server.listen ( the); Console.log (' Listening at port ... ');
From the above code we can see that when the server receives the request, it will determine whether the request resource is JS, if it is delayed after 1s to return the corresponding resources.
Starting this service is simple, just execute it node server.js , then you can enter it in the browser http://localhost:3000/app/index.html , and now let's look at index.html the content:
<! DOCTYPE html><html> <head> <title>Defer & Async</title> <link rel="stylesheet" type="text/css" href= "Css/main.css"> <script type="text/javascript" src="Js/1.js"> </script> </head> <body> <div class="text">Hello World</div> <script type="text/javascript" src="Js/2.js"> </script> </body></html>
In this HTML document, we refer to an head external script file in, js/1.js and then reference one after the Hello world we want to display js/2.js , and their contents are simple, that is, to pop up the corresponding marker information:
// js/1.jsalert(1);// js/2.jsalert(2);
Let's go to the homepage and see what happens:
You can see that the process of rendering is really top-down, synchronous, that is, encounter external script, you have to pause the parsing of the document, download and interpretation of execution, this way is blocked, will cause the Web page blank phenomenon.
Now change the code a little bit, add the head tags in the script defer property, and then change the two JS files a little bit:
<! DOCTYPE html><html> <head> <title>Defer & Async</title> <link rel="stylesheet" type="text/css" href= "Css/main.css"> <!--Adding a ' defer ' attribute, by default, the value would be ' true ' -- <script type="text/javascript" src="Js/1.js " defer ></script> </head> <body> <div class="text">Hello World</div> <script type="text/javascript" src="Js/2.js"></script> </body></html>
// js/1.jsconsole.log(1);// js/2.jsconsole.log(2);
Again index.html , we'll see the following order of execution in the console:
It is obvious that the delay is followed by the completion of the 1.js document parsing, and its execution order is later than the body Middle <script> . Unlike the default synchronization resolution, the defer download of external scripts is not blocked, the browser will open a separate thread for network connection download, the process, the document parsing and building the DOM can still continue to do not appear due to download script page blank.
Here are a defer few things to keep in mind:
1. defer applies only to the external script, if the script label does not specify src a property, only inline script, do not use defer
2. If there are multiple scripts that have been declared, they are defer downloaded and executed sequentially
3. defer scripts are DOMContentLoaded executed before and after the load event
Let's change the code a little bit and verify the above:
<! DOCTYPE html><html> <head> <title>Defer & Async</title> <link rel="stylesheet" type="text/css" href="css /main.css "> <!--Adding a ' defer ' attribute, by default, the value would be ' true ' -- <script type="text/javascript" src="Js/1.js " Defer></script> <script type="text/javascript" src="Js/2.js " defer ></script> <script type="Text/javascript" defer>Console.log (3); </script> </head> <body> <div class="text">Hello World</div> <script type="Text/javascript">Document.addeventlistener ("domcontentloaded", function() { Console.log (' DOM content loaded, ready state: ', this. readyState); }, false); Window.addeventlistener (' Load ', function() { console.log (' Wind ow loaded, Dom ready state: ', document.readystate); }, false); </script> </body></html>
In the above code, head all the script tags are added, and the defer third one is inline script, and then we also add the DOMContentLoaded and load events, and look at the printed results:
As you can see, the outer script is executed in the order of declaration, the inline script does not follow this rule, and, in addition, the DOMContentLoaded load events are captured sequentially, and DOM the state is changed into a interactive and complete .
Let's take a look at the async properties and, in order to demonstrate the execution sequence well, we need some modifications:
<! DOCTYPE html><html> <head> <title>Defer & Async</title> <link rel="stylesheet" type="text/css" href="css /main.css "> <!--Adding a ' async ' attribute, by default, the value was ' true ' as well-- <script type="text/javascript" src="Js/1.js " Async></script> <script type="text/javascript" src="Js/2.js" async ></script> <script type="text/javascript" src="Js/3.js " Async></script> </head> <body> <div class="text">Hello World</div> </body></html>
JS file in the following:
// js/1.jsconsole.log(1);// js/2.jsconsole.log(2);// js/3.jsconsole.log(3);
Once again index.html , you will find that the console prints as follows:
We found that the execution of 3 scripts was not sequential, and we could not predict the time and order in which each script was downloaded and executed. asyncand defer , as it does, it does not block parsing of the current document, it asynchronously downloads the script, but, defer unlike that, it async executes immediately after the script is downloaded, if there is a dependency between the scripts in the project, it is not recommended async .
The async following points also need to be noted:
1. Applies only to the outreach script, which is defer consistent with
2. If there are multiple scripts that have been declared async , their download and execution are asynchronous and do not guarantee the order of each other.
3. async will be load executed before the event, but does not ensure that DOMContentLoaded the execution sequence
The following two graphs can be more clearly articulated defer and async implemented, and the relationship between the and DOMContentLoaded load events:
Image source: Asynchronous and deferred JavaScript execution explained
Image source: Running Your Code at the right time
The above is defer and async the introduction, understand and grasp the role of these two attributes, not only to the control of the JS code execution more proficient, but also to the page rendering more understanding.
Defer and Async