Inject a script tag with remote src and wait for it to execute

You could use Google Analytics or Facebook's method:

(function(d, script) {
    script = d.createElement('script');
    script.type = 'text/javascript';
    script.async = true;
    script.onload = function(){
        // remote script has loaded
    };
    script.src = 'http://www.google-analytics.com/ga.js';
    d.getElementsByTagName('head')[0].appendChild(script);
}(document));

UPDATE:

Below is the new Facebook method; it relies on an existing script tag instead of <head>:

(function(d, s, id){
    var js, fjs = d.getElementsByTagName(s)[0];
    if (d.getElementById(id)){ return; }
    js = d.createElement(s); js.id = id;
    js.onload = function(){
        // remote script has loaded
    };
    js.src = "//connect.facebook.net/en_US/sdk.js";
    fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
  • Replace facebook-jssdk with your unique script identifier to avoid it being appended more than once.
  • Replace the script's url with your own.

This is one way to dynamically load and execute a list of scripts synchronously. You need to insert each script tag into the DOM, explicitly setting its async attribute to false:

script.async = false;

Scripts that have been injected into the DOM are executed asynchronously by default, so you have to set the async attribute to false manually to work around this.

Example

<script>
(function() {
  var scriptNames = [
    "https://code.jquery.com/jquery.min.js",
    "example.js"
  ];
  for (var i = 0; i < scriptNames.length; i++) {
    var script = document.createElement('script');
    script.src = scriptNames[i];
    script.async = false; // This is required for synchronous execution
    document.head.appendChild(script);
  }
  // jquery.min.js and example.js will be run in order and synchronously
})();
</script>

<!-- Gotcha: these two script tags may still be run before `jquery.min.js`
     and `example.js` -->
<script src="example2.js"></script>
<script>/* ... */<script>

References

  • There is a great article by Jake Archibald of Google about this called Deep dive into the murky waters of script loading.
  • The WHATWG spec on the tag is a good and thorough description of how tags are loaded.

Same method using event listeners and ES2015 constructs:

function injectScript(src) {
    return new Promise((resolve, reject) => {
        const script = document.createElement('script');
        script.src = src;
        script.addEventListener('load', resolve);
        script.addEventListener('error', e => reject(e.error));
        document.head.appendChild(script);
    });
}

injectScript('https://example.com/script.js')
    .then(() => {
        console.log('Script loaded!');
    }).catch(error => {
        console.error(error);
    });

Tags:

Javascript