ThePerplexedOne ThePerplexedOne - 19 days ago 6
Javascript Question

Waiting for multiple $.getJSON to complete

Before I get started, I want to mention that I don't have much experience with promises/deferred objects in JavaScript.

What I'm trying to achieve, is when a user clicks a button, it runs multiple

$.getJSON
requests, handles the responses and updates the page accordingly.

I also need to notify the user when all of these requests have been completed, here is the
connect
method I have which handles the first part I spoke about:

function connect(row) {
return new Promise(function(resolve, reject) {
var trees = $("#selectedTree").val();
var employee_id = row.attr("rel");

var columns = row.children();
var emailColumn = $(columns[1]);
var firstNameColumn = $(columns[2]);
var lastNameColumn = $(columns[3]);
var jobTitleColumn = $(columns[4]);
var statusColumn = $(columns[5]);
var actionsColumn = $(columns[6]);

actionsColumn.html("<span class='spinner'><i class='fa fa-spinner fa-spin'></i></span>");
$.getJSON("functions/connect_with.php", {
employee_id: employee_id,
trees: trees
}, function(response) {
emailColumn.html(response.message.person.email);
actionsColumn.html("<i class='text-success fa fa-check'></i>");
if(response.success) {
firstNameColumn.html(response.message.person.name.givenName);
lastNameColumn.html(response.message.person.name.familyName);
jobTitleColumn.html(response.message.person.employment.title);
}
statusColumn.html("<i class='text-success fa fa-sitemap'></i>");
resolve(true);
});
});
}


And this is what happens when the user clicks said button:

$("#connectAll").click(function() {
alert("OFF WE GO");
$(this).hide();
var methods = [];
$(".staffMember input:checked").each(function(index, checkbox) {
checkbox = $(checkbox);
var row = checkbox.parents("tr");
methods.push(connect(row));
});
$.when.apply($, methods).then(function () {
alert("WE DID IT MOM");
$("#connectAll").show();
});
});


However, both alerts are sent immediately after one another, and is not waiting for the requests to complete. I've tried other methods of doing this and I can't seem to get it right.

Answer

Rather than calling apply use Promise.all

This executes an array of promises and returns once all have completed.

So your code would become:

$("#connectAll").click(function() {
  alert("OFF WE GO");
  $(this).hide();
  var methods = [];
  $(".staffMember input:checked").each(function(index, checkbox) {
    checkbox = $(checkbox);
    var row = checkbox.parents("tr");
    methods.push(connect(row));
  });
  Promise.all(methods).then(values => {
    alert("WE DID IT MOM");
    $("#connectAll").show();   
  }).catch(reason => {
    alert("MOM, SOMETHING WENT WRONG");
  });
});
Comments