Bjarne Hansen
Bjarne Hansen

Reputation: 43

Waiting for all functions and requests to finish

Right now I've got some code that takes in an array of strings of the modules I wish to load

script.js

moduleLoader.load([
    'mainModule',
    'aboutUsModule',
    'featuresModule',
    'messageModule'
]);

The moduleLoader.load function does an $.each loop on the array and then proceeds to get the required information about each module.

moduleLoader

var load = function (modules) {
    $.each(modules, function (index, module) {
        getConfig(module);
    });
};

getConfig

var getConfig = function (module) {
    $.get(module + '/config.json').done(function (config) {
        console.log(config);
        getData(config);
    }).fail(function () {
        console.error('Couldn\'t find a config file for module: ' + module);
        return 0;
    });
};

Then you can see in the getConfig callback that it proceeds to get data, which is also async, and then it has two more steps after that which is async.

So it's basically callback inside callback inside callback... etc..

Just that I divided it into functions so that it looks a bit nicer.

Now I can get all the info, but it loads differently every time, so is it possible to know when all the ajax requests are done, and then do something?

Upvotes: 3

Views: 96

Answers (3)

A. Wolff
A. Wolff

Reputation: 74420

If you have no other pending ajax requests, then use relevant global ajax event ajaxStop:

$( document ).one('ajaxStop', function() {
  // all ajax requests has finished
});

Upvotes: 0

VladNeacsu
VladNeacsu

Reputation: 1288

You could use the jQuery function $.when() that does exactly what you need: https://api.jquery.com/jquery.when/

To make your code work you can refactor a bit:

var XHRs = [];

var load = function (modules) {
  $.each(modules, function (index, module) {
    XHRs.push(getConfig(module));
  });
};

$.when(XHRs).then(function() {
  // do something
});

And also your getConfig() function should return the $.get. This works because $.ajax in jQuery creates a Deferred object that actually lets you chain your functions or make them wait each other.

For future reference: https://api.jquery.com/jquery.deferred/

Upvotes: 2

Naftali
Naftali

Reputation: 146300

You can utilize promise chaining and group them all together and do something when they are all done (kind of like this):

var load = function (modules) {
    var promises = modules.map(getConfig);

    // can use $.when or Promise.all here
    $.when.apply($, promises).then(function () {
         // do something when all done
    });
};

var getConfig = function (module) {
    // $.get returns a jqXHR which is "thennable"
    return $.get(module + '/config.json').then(function (config) {
        console.log(config);
        // if this also returns a promise then it will
        // wait till this one is done as well in the promise chain
        return getData(config); 
    }, function () {
        console.error('Couldn\'t find a config file for module: ' + module);
        return 0;
    });
};

Upvotes: 2

Related Questions