views:

396

answers:

4

If I have an ajax call off fetching (with a callback) and then some other code running in the meantime. How can I have a third function that will be called when both of the first 2 are done. I'm sure it is easy with polling (setTimeout and then check some variables) but I'd rather a callback.

Is it possible?

+7  A: 

You could just give the same callback to both your AJAX call and your other code running in the meantime, use a variable to track their combined progress, then link them to a callback like below:

// Each time you start a call, increment this by one
var counter = 0;

var callback = function() {
    counter--;
    if (counter == 0) {
        // Execute code you wanted to do once both threads are finished.
    }
}
Daniel Lew
Since there is no real multi-threading in JS (yet) this is also safe to do.
Jabe
The problem here is that one of the "threads" isn't really finished when it calls callback() function from its context.
Thevs
Thevs: That's exactly why there's a counter, so that it only continues execution once both "threads" have finished. Note that this isn't a complete answer, and purposefully so; I'm assuming some intelligence on the part of the asker, such that they can fill in the gaps however they feel is necessary. I'm just trying to provide the basic idea on how to solve this problem.
Daniel Lew
Yes, I understand. I just wanted to underline such detail.
Thevs
+3  A: 

Daniel's solution is the proper one. I took it and added some extra code so you don't have to think too much ;)

function createNotifier() {
    var counter = 2;
    return function() {
        if (--counter == 0) {
            // do stuff
        }
    };
}

var notify = createNotifier();
var later = function() {
    var done = false;
    // do stuff and set done to true if you're done
    if (done) {
        notify();
    }
};

function doAjaxCall(notify) {
    var ajaxCallback = function() {
        // Respond to the AJAX callback here
        // Notify that the Ajax callback is done
        notify();
    };
    // Here you perform the AJAX call action
}

setInterval(later, 200);
doAjaxCall(notify);
Helgi
A: 

Something like this (schematic):

registerThread() {
  counter++;
}

unregisterThread() {
  if (--counter == 0) fireEvent('some_user_event");
}

eventHandler_for_some_user_event() {
   do_stuff();
}
Thevs
+1  A: 

The best approach to this is to take advantage of the fact that functions are first-order objects in JavaScript. Therefore you can assign them to variables and invoke them through the variable, changing the function that the variable refers to as needed.

For example:

function firstCallback() {
    // the first thing has happened
    // so when the next thing happens, we want to do stuff
    callback = secondCallback;
}

function secondCallback() {
    // do stuff now both things have happened
}

var callback = firstCallback;

If both your pieces of code now use the variable to call the function:

callback();

then whichever one executes first will call the firstCallback, which changes the variable to point to the secondCallback, and so that will be called by whichever executes second.

However your phrasing of the question implies that this may all be unnecessary, as it sounds like you are making an Ajax request and then continuing processing. As JavaScript interpreters are single-threaded, the Ajax callback will never be executed until the main body of code that made the request has finished executing anyway, even if that is long after the response has been received.

In case that isn't your situation, I've created a working example on my site - as StackOverflow won't yet let me post links, you'll have to go to www.nickfitz.co.uk/examples/javascript/switching-functions.html manually; view the source to see the code (just before the </body> tag). It makes a request which is delayed by the server for a couple of seconds, then a request which receives an immediate response. The second request's response is handled by one function, and the first request's response is later handled by a different function, as the request that received a response first has changed the callback variable to refer to the second function.

NickFitz