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.