9

I'm looking for a Thread.Join() type thing. Lets say I trigger 4 events in javascript. I want to execute code but only after all 4 callbacks have been completed. How do I do that? The only way I can think of is checking if any the 4 callbacks are in process via global var in which case i ignore or throw exception. But otherwise do something like globalVar++ in each callback and call IsItDone() at the end of each callback which checks if the globalVar is == 4.

But.. I kind of dont like it especially since I need to use a global var.

4

2 に答える 2

9

You can string up a queue and wrap callbacks yourself buts it sort of hairy. Luckily there are a ton of libraries out there to help. I'm not a fan of the counter approach because sometimes it's hard to know which callbacks haven't fired yet.

I'm a fan of the "Deferred" style. Such as this library: https://github.com/heavylifters/deferred-js

Or for a totally different API, see Step.js https://github.com/creationix/step

Or see here for other micro libs that encapsulate this issue: http://microjs.com/#defer


Or just do it yourself by calling setting some external state, and then calling a shared done function in every callback.

var complete = {
  first: false,
  second: false
};

doFirstAsync(function() {
  complete.first = true;
  allDone();
});

doSecondAsync(function() {
  complete.second = true;
  allDone();
});

var allDone = function() {
  if (complete.first && complete.second) {
    alert("done with all async!");
  }
};

Most of the libraries above do this for you based on a similar approach. But just abstracted and generalized. That generalization is where things can get hairy, as you have arrays of callbacks functions flying everywhere. It's fun functional programming, but it can get conceptually complex.

If you are doing this all over, use a lib that has an API you like.

于 2013-01-13T00:57:14.200 に答える
4

If you don't mind adding jQuery to your site you can use its "deferred object" capability.

Each async function (include jQuery's built-in AJAX functions) can return a "promise" to return something later.

To achieve what you're asking for you can then call:

$.when(p1, p2, p3, p4).done(function() {
    // this will be called only when
    // all of p1 - p4 have been "resolved"
});

If you prefer to have an array p containing those promises instead, call $.when like this instead:

$.when.apply($, p).done(function() {
    ...
});
于 2013-01-13T01:10:33.547 に答える