1
\$\begingroup\$

I made a simple script to load other scripts into the page without worrying about caching. It's meant to be used by a considerable amount of people, so I would like it to be as clean as possible, and I would like your advice.

window.load_scripts = function () {
    var callbacks = {
        jqueryCallback: function (script_path) {
            $.getScript(script_path, function (data, textStatus, jqxhr) {
                if (jqxhr.status === 200) {
                    console.log(script_path + ' loaded correctly.');
                } else {
                    console.log(script_path + ' failed to load');
                }
            });
        },
        vanillaCallback: function (script_path) {
            var script = document.createElement('script');
            script.src = script_path + '?d=' + (new Date()).getTime();
            document.head.appendChild(script);
        }
    }
    var callback;
    //if we don't have arguments, just return.
    //no scripts have to be loaded
    if (!arguments || !arguments.length)
        return;

    //if we have jquery, we will use $.getScript
    callback = window.$ ? callbacks['jqueryCallback'] : callbacks['vanillaCallback'];

    //loop through all scripts 
    for (let i = 0; i < arguments.length; i++) {
        var path = arguments[i];
        //just be sure that the argument is a string
        if (typeof path === "string") {
            callback(path);
        }
    }
}
\$\endgroup\$

1 Answer 1

4
\$\begingroup\$

few suggestions...

  • I would lose the jQuery part and stick to vanilla js for several reasons
    • jQuery's getScript doesn't add a script to the page like your vanilla example does, getScript actually uses eval to execute the code, which means any safe mode scripts will not be able to change any global state.
    • $ is used by lots of libraries, not just jQuery. There's a real high chance you're going to get a false positive if you're only checking for $ rather than jQuery.
    • The jQuery code is just unnessecary. Your vanilla code will always work, there is no benefit to using jQuery.
  • Don't forget to add your onload callback so scripts that use this to include other scripts can use those other scripts after they have loaded.
  • Declare your function. There is no benefit to doing window.whatever = function(){};. when you use function whatever(){} the function does not need to be defined at the top of the script, plus it's less bits.

Here's a function I wrote to include jQuery and stuff in userscripts, feel free to take it or parts of it.

function loadScripts(scripts, appendTo) {
  appendTo = appendTo || "body";
  return new Promise((done) => {
    (function recurse(i) {
      if (undefined === scripts[i]) return done();
      let src = scripts[i];
      let script = document.createElement('script');
      script.type = 'text/javascript';
      if (script.readyState) { //IE
        script.onreadystatechange = () => {
          if (script.readyState == 'loaded' || script.readyState == 'complete') {
            script.onreadystatechange = null;
            setTimeout(() => {
              recurse(++i);
            }, 1);
          }
        };
      } else { //Others
        script.onload = () => {
          setTimeout(() => {
            recurse(++i);
          }, 1);
        };
      }
      script.src = src;
      document.getElementsByTagName(appendTo)[0].appendChild(script);
    })(0);
  });
}

// Example usage
loadScripts(["https://code.jquery.com/jquery-2.2.4.min.js"]).then(()=>{
  $("body").append("loaded with jQuery");
});

\$\endgroup\$
2
  • \$\begingroup\$ Note that if you jump through all of the function calls that $.getScript makes - it actually does the same thing that the OP’s code does but removes the script element after it has executed. \$\endgroup\$
    – Gerrit0
    Oct 14, 2017 at 16:21
  • \$\begingroup\$ glad to hear that. come to think of it, I was maintaining a pretty old code base when I ran into the issue with getscript using eval so that was likely with an old version of jquery. \$\endgroup\$ Oct 14, 2017 at 17:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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