Francis Ducharme Francis Ducharme - 1 month ago 7
Javascript Question

Many requests with final callback, unreliable order?

I'm trying to come up with a resource loader if you will, that will load many remote resources and then execute a final callback (like rendering a DOM based on the retrieve data from these requests).

Here's the function:

var ResourceLoader = function () {

this.requests = new Array();
this.FinalCallback;

this.Add = function (request) {
this.requests.push(request);
};

this.Execute = function() {

for (var x = 0; x < this.requests.length ; x++) {

var success = this.requests[x].success;

//if this is the last of the requests...
if (x == (this.requests.length - 1) && this.FinalCallback) {

$.when($.ajax({
url: this.requests[x].url,
dataType: 'json',
error: this.requests[x].error,
method: 'GET'
}).done(success)).then(this.FinalCallback);
}
else {

$.ajax({
url: this.requests[x].url,
dataType: 'json',
error: this.requests[x].error,
method: 'GET'
}).done(success);
}

}

};
};


And here's how I use it:

var apiUrl = Utilities.Api.GetWebApiUrl();
var loader = new Utilities.ResourceLoader();

loader.Add({
url: apiUrl + 'regions/get',
success: function (results) {
Filters.Regions = results;
}
});

loader.Add({
url: apiUrl + 'currentfactors/get/83167',
success: function (results) {
Filters.NbrEmployees = results;
}
});

loader.Add({
url: apiUrl + 'currentfactors/get/83095',
success: function (results) {
Filters.Industries = results;
}
});


loader.FinalCallback = RenderBody;
loader.Execute();

function RenderBody() {
console.log('render...');
}


Obviously, I'm expecting
RenderBody
to be executed last. But that's not what happening. What's ironic is that I remember doing something like that before, but lost the code... Looks like I'm having a brainfart here.

Answer

As you've tagged with - here's a really clean solution that uses Promise.all

this.Execute = function() {
  Promise.all(this.requests.map(function(request) {
    return $.ajax({
        url: request.url,
        dataType: 'json',
        error: request.error,
        method: 'GET'
    }).done(request.success);
  })).then(this.FinalCallback);
};

or ... using JQuery when

this.Execute = function() {
  $.when.apply($, this.requests.map(function(request) {
    return $.ajax({
        url: request.url,
        dataType: 'json',
        error: request.error,
        method: 'GET'
    }).done(request.success);
  })).then(this.FinalCallback);
};