dabadaba
dabadaba

Reputation: 9542

Call function when the last one has finished

I am sure it looks like this question has been asked a lot before, but it's not the typical async JS question "how to call a function only when another one has finished?".

So my scenario is the following: I need to load a pretty heavy set of data with AJAX, a list of matches arranged in the weeks where they're played. I set up an array of promises and when they're all done I do something else once I have all the matches in the DOM. I had something like this:

var promises = [];
for (var i = 1; var i <= lastWeek; i++)
  promises.push($.ajax({
    url: "week/" + i,
    success: { ... }
  }));

$.when.apply($, promises).done(someFunction);

However I noticed this would fire all requests at once and could clog the process in the server side and malfunction in general. So I figured I would approach this differently, instead of making all those requests at once I make one for the first week, and once that one's done, I make the following, and so on:

function loadWeek(week, last) {
  $.get("week/" + i, function (response) {
    // do whatever with the response
    // make the request for the next week
    if (week + 1 <= last)
      loadWeek(week + 1, last);
  });
}

Now of course I cannot use $.when because the promises are generated on the fly as the previous one is completed.

I wonder if there is a way JS or jQuery offers to signal the someFunction function (the one that should be called only after all matches have been loaded) after the last week has been loaded.

Of course, you could say, just call it when week + 1 > last right? Well, I still need to work with promises because this someFunction not only needs to wait for these matches to be loaded but also for another promise to complete.

So you could say I lied a little when I said I was doing this:

$.when.apply($, promises).done(someFunction);

When in reality, promises actually have more function calls other than the list of matches, and someFunction should have until all of them have finished.

Upvotes: 1

Views: 1364

Answers (3)

man
man

Reputation: 197

Ok so lets break this down, if I understood you correctly you want the following

A- Load weeks sequentially

function loadWeek(week, last) {
    var deferred = $.Deferred();

    (function request(week, last) {
        $.get("week/" + i, function (response) {
            // do whatever with the response
            // make the request for the next week
            if (week + 1 <= last)
                request(week + 1, last);
            else
               deferred.resolve();
        });
    })(week, last);

    return deferred.promise();
}

B- Load other stuff in the mean time

function otherStuff() {
    // return some promise
}

C- when A and B are done call someFunction

var promises = []
promises.push(loadWeek(1, 10));
promises.push(otherStuff(...));
$.when.apply($, promises).done(someFunction);

Upvotes: 1

Jonas Wilms
Jonas Wilms

Reputation: 138557

You want a function that runs when a promise, and a function finishes. Small Workaround:

 var c=0;
 function callbyboth(){
 c++;
 if(c==2){
  //both executed
  //run your code
 }
 }

Add this on your promise

Promise.then(callbyboth);

And at the recursive function:

if(week+1>=last){
  callbyboth();
}else{
 //recursion
}

Upvotes: 0

T.J. Crowder
T.J. Crowder

Reputation: 1075815

There are several ways, but one of the simplest is to just make a small tweak to your attempt (see ***):

function loadWeek(week, last, done) {      // ***
  $.get("week/" + i, function (response) {
    // do whatever with the response
    // make the request for the next week
    if (week + 1 <= last) {
      loadWeek(week + 1, last, done);      // ***
    } else {                               // ***
      done();                              // ***
    }                                      // ***
  });
}

then only push the other promises into promises (not the ones from loadWeek above), and:

loadWeek(1, lastWeek, function() {
    $.when.apply($, promises).then(someFunction);
});

Upvotes: 0

Related Questions