M Miller
M Miller

Reputation: 5662

How can I force an array of scripts to load in sequential order?

I am building a single-page web application and each "widget" may require one or more JavaScript or jQuery libraries. Some of those scripts may depend on other scripts, but if I just create a series of $.getScript calls, they may load out of order. How can I force that the scripts are loaded in order, i.e. that the process waits for script 1 to download before requesting script 2, etc.?

Upvotes: 0

Views: 1264

Answers (3)

alettieri
alettieri

Reputation: 396

You could use the reduce method on the array of script names.

Here is an example of this approach:

// Load Script and return promise
function loadScript(script) {
  return $.getScript(script);
}
/**
 * Load list of scripts
 */
function loadScripts(scripts) {
  // Reduce, causes sequenctial order of execution
  return scripts.reduce(function(cur, next){
    // When promise is complete, return next promise (loadScript)
    return cur.then(function(){
      console.log(next);
      // Load the next script and return promise
      return loadScript(next);
    });
  }, $().promise() /* First promise is an empty promise */); 
}

(JSBin)

Or in short:

function loadScripts(scripts) {
    return scripts.reduce(function(cur, next){ 
        return cur.then($.getScript.bind($, next));
    }, $.when());
}
loadScripts(["./1.js","./2.js","./3.js").then(function(){ // example usage
    // all done here
});

Upvotes: 2

Rajkumar Madhuram
Rajkumar Madhuram

Reputation: 684

You can use the async library to ensure all the libraries are loaded in order. https://github.com/caolan/async#eachSeries

Alternatively, as one other user pointed out, you can use require.js

Upvotes: 0

M Miller
M Miller

Reputation: 5662

This function accepts an array of URIs to scripts and loads them in order, returning a jQuery promise that will resolve when the last script in the set has loaded.

$.load_scripts_sequentially = function (scripts) {
    var deferred = new $.Deferred();
    var load_script = function (index) {
        var scripts = this;
        if (index > scripts.length - 1) {
            deferred.resolve();
            return;
        }
        $.getScript(scripts[index])
            .done($.proxy(function () {
                load_script.call(this.scripts, this.index + 1);
            }, {scripts: scripts, index: index}))
            .fail($.proxy(function () {
                console && console.error('Failed to load script: ' + this.scripts[this.index], arguments);
                deferred.reject();
            }, {scripts: scripts, index: index}));
    };
    load_script.call(scripts, 0);
    return deferred.promise();
};

Example usage:

$.load_scripts_sequentially(['1.js', '2.js', '3.js']).done(function () {
    console && console.info('All scripts done loading!');
});

Upvotes: 0

Related Questions