5

I try to write a JavaScript function that loads a js script (src) and performs some callback when the script is loaded.

I also look if a script with the same src already exists.

My problem is that if the script already loaded, the callback will not be performed. That is NOK.

How to know if the script was already loaded?

importScript: (function (head) {

    function loadError(error) {
        throw new URIError("The script " + 
                            error.target.src + " is not accessible.");}

    return function (url, callback) {
        var existingScript = document.querySelectorAll("script[src='" + 
                             url + "']");
        var isNewScript = (existingScript.length == 0);
        var script;
        if (isNewScript) {
            script = document.createElement("script")
            script.type = "text/javascript";
        }
        else {
            script = existingScript[0];
        }
        script.onerror = loadError;
        if (script.readyState) { //IE
            script.onreadystatechange = function () {
                if (script.readyState == "loaded" || 
                    script.readyState == "complete") {
                    script.onreadystatechange = null;
                    if (callback) {
                        callback(); }
                }
            };
        } else { // others than IE
            script.onload = callback; }

        if (isNewScript) {
            script.src = url;
            head.appendChild(script); }
    }
})(document.head || document.getElementsByTagName("head")[0])

As I understand, the script.readyState == "loaded" || script.readyState == "complete" could work only for IE, not for other browsers as well...

Usage:

importScript("myScript1.js");
importScript("myScript2.js", /* onload function: */ 
            function () { alert("The script has been OK loaded."); });
2
  • if (isNewScript) {script.src = ...} else {callback(false);}, and check the passed parameter in the callback to detect, if the script was actually loaded?
    – Teemu
    Commented Mar 31, 2015 at 18:22
  • Does this answer your question? Verify External Script Is Loaded
    – Frédéric
    Commented Dec 30, 2020 at 10:30

3 Answers 3

9

I recommend jQuery, it's so easy with that. Life is too short for coding things like that yourself (you will waste hours for supporting all browsers).

$.ajax({
  url: "/script.js",
  dataType: "script",
  success: function() {
    console.log("script loaded");
  }
});

EDIT:
It's even easier (example from jQuery docs):

$.getScript( "ajax/test.js", function( data, textStatus, jqxhr ) {
  console.log(data); // Data returned
  console.log(textStatus); // Success
  console.log(jqxhr.status); // 200
});

You can also chain done and fail to have additional callbacks:

$.getScript("ajax/test.js")
  .done(function(script, textStatus) {
    console.log(textStatus);
  })
  .fail(function(jqxhr, settings, exception) {
    console.log("loading script failed.");
  });

Load jQuery asynchronously

<script src="path/to/jquery"></script>
<script>
function wait(method) {
    if (window.$) {
        method();
    } else {
        setTimeout(function () { wait(method); }, 100); // check every 100ms
    }
}

// wait for jQuery
wait(function() {
    // jQuery has loaded!
    $("#foo").doSomething();

    // you can now load other scripts with jQuery:
    $.getScript("ajax/test.js")
      .done(function(script, textStatus) {
        console.log(textStatus);
      })
      .fail(function(jqxhr, settings, exception) {
        console.log("loading script failed.");
      });
}
</script>
3
  • This is a better solution.
    – Y123
    Commented Mar 31, 2015 at 18:49
  • Thanks. I wonder how to check if the script was loaded, not how to load the script, because I am not sure if jQuery is loaded at the moment, so I'd really prefer pure JavaScript
    – serhio
    Commented Apr 1, 2015 at 7:58
  • Please check my answer, I added some code to load jquery asynchronously too.
    – Luca Steeb
    Commented Apr 1, 2015 at 12:26
1

Well the safest way to check if script is loaded is you can add a simple callback at end of script . Which if exist can be called with some data also to be passed.

if(window.loaded){
  window.loaded(params);
}

Once the script loads it will execute this method which you can declare in your parent script which will be called.

Also you can trigger an event on body and listen on that event in other parent code.

1
  • Very convenient : just add a script tag with the poper src and launch thanks ti a callback at the end of the loaded script. Thanks !
    – PhilMaGeo
    Commented Jan 15, 2018 at 8:09
0

Based on method from Luca Steeb, I refine the solution to just two script tags, for SPA applications, index.html is very compact with:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Simplified INDEX</title>

    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <script src="/bootloader.js"></script>
</head>

<body>
</body>

</html>

bootloader.js, combine ideas from Luca and load css using jquery :

function loadScripts() {
  // jQuery has loaded!
  console.log("jquery is loaded");

  // you can now load other scripts and css files with jQuery:
  $.when($.getStylesheet('css/main.css'), $.getScript('js/main.js'))
    .then(function () {
       console.log('the css and js loaded successfully and are both ready');
    }, function () {
        console.log('an error occurred somewhere');
    });
}

function patchGetStylesheet($) {
  $.getStylesheet = function (href) {
    var $d = $.Deferred();
    var $link = $('<link/>', {
      rel: 'stylesheet',
      type: 'text/css',
      href: href
    }).appendTo('head');
    $d.resolve($link);
    return $d.promise();
  };
}

function wait(method) {
  if (window.$) {
    patchGetStylesheet(window.$);
    method();
  } else {
    setTimeout(function () {
      wait(method);
    }, 100); // check every 100ms
  }
}

// wait for jQuery
wait(loadScripts);

For bootloader.js, it could be minified、obfused.... using webpack, ...

We will not add code to index.html any more through solving runtime dependency using jquery.

Not the answer you're looking for? Browse other questions tagged or ask your own question.