Manngo
Manngo

Reputation: 16369

JavaScript async & defer: run a script asynchronously

As far as I am aware, in the script element, the async attribute allows the script to download asynchronously (similar to images), while the defer causes the script to wait until the end before executing.

Suppose I have two scripts to include:

<script src="library.js"></script>
<script src="process.js"></script>

I would want them both to proceed asynchronously, and I would want process.js to wait until the end to start processing.

Is there a way to get the library.js script to run asynchronously?

Note

I see there appears to be some discrepancy between different online resources as to the actual role of the async attribute.

MDN & WhatWG suggest that it means that the script should execute asynchronously. Other online resources suggest that it should load asynchronously, but still blocks rendering when it is executed.

Upvotes: 1

Views: 3255

Answers (2)

Mamun
Mamun

Reputation: 68923

I found Sequential script loading in JavaScript which might help you:

(function(){
  
  //three JS files that need to be loaded one after the other
  var libs = [
    'https://code.jquery.com/jquery-3.1.1.min.js',
    'https://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.4.1/jquery.easing.min.js',
    'https://cdnjs.cloudflare.com/ajax/libs/underscore.string/3.3.4/underscore.string.js'
  ];
  
  var injectLibFromStack = function(){
      if(libs.length > 0){
        
        //grab the next item on the stack
        var nextLib = libs.shift();
        var headTag = document.getElementsByTagName('head')[0];
        
        //create a script tag with this library
        var scriptTag = document.createElement('script');
        scriptTag.src = nextLib;
        
        //when successful, inject the next script
        scriptTag.onload = function(e){
          console.log("---> loaded: " + e.target.src);
          injectLibFromStack();
        };    
        
        //append the script tag to the <head></head>
        headTag.appendChild(scriptTag);
        console.log("injecting: " + nextLib);
      }
      else return;
  }
  
  //start script injection
  injectLibFromStack();
})();

Upvotes: 3

Flimm
Flimm

Reputation: 151123

Both defer and async affect when a script is executed, not when a script is downloaded. I think the confusion comes from the fact that some documentation is a bit sloppy with terms, and the term loaded is unclear as to whether it refers to the fetching of the resource, or the execution of it.

To get library.js to run asyncronously without waiting for the document to load, use async attribute, and to get process.js to wait until document has been parsed, use defer:

<script src="library.js" async></script>
<script src="process.js" defer></script>

Note that library.js is not guaranteed to run before process.js, although it probably will.

Upvotes: 1

Related Questions