Stefan Kendall
Stefan Kendall

Reputation: 67832

Javascript - waiting for a number of asynchronous callbacks to return?

What's the best way/library for handling multiple asynchronous callbacks? Right now, I have something like this:

_.each(stuff, function(thing){
   async(thing, callback);
});

I need to execute some code after the callback has been fired for each element in stuff.

What's the cleanest way to do this? I'm open to using libraries.

Upvotes: 14

Views: 17160

Answers (6)

skashyap
skashyap

Reputation: 143

async.parallel() / async.series should suit your requirement. You can provide with a final callback that gets executed when all the REST calls succeed.

async.parallel([
    function(){ ... },
    function(){ ... }
], callback);
async.series([
    function(){ ... },
    function(){ ... }
], callback);

Upvotes: 1

Jamund Ferguson
Jamund Ferguson

Reputation: 17014

There is a great library called Async.js that helps solve problems like this with many async & flow control helpers. It provides several forEach functions that can help you run callbacks for every item in a an array/object.

Check out: https://github.com/caolan/async#forEach

// will print 1,2,3,4,5,6,7,all done

var arr = [1,2,3,4,5,6,7];

function doSomething(item, done) {
  setTimeout(function() {
    console.log(item);
    done(); // call this when you're done with whatever you're doing
  }, 50);
}

async.forEach(arr, doSomething, function(err) {
    console.log("all done");
});

Upvotes: 13

Peter Lyons
Peter Lyons

Reputation: 146084

I recommend https://github.com/caolan/async for this. You can use async.parallel to do this.

function stuffDoer(thing) {
    return function (callback) {
        //Do stuff here with thing
        callback(null, thing);
    }
}

var work = _.map(stuff, stuffDoer)
async.parallel(work, function (error, results) {
    //error will be defined if anything passed an error to the callback
    //results will be an unordered array of whatever return value if any
    //the worker functions passed to the callback
}

Upvotes: 2

slebetman
slebetman

Reputation: 113926

See my response to a similar question:

Coordinating parallel execution in node.js

My fork() function maintains the counter internally and automatically.

Upvotes: 0

Jordan Running
Jordan Running

Reputation: 106047

Since you're already using Underscore you might look at _.after. It does exactly what you're asking for. From the docs:

after    _.after(count, function)

Creates a version of the function that will only be run after first being called count times. Useful for grouping asynchronous responses, where you want to be sure that all the async calls have finished, before proceeding.

Upvotes: 28

Niet the Dark Absol
Niet the Dark Absol

Reputation: 324690

Have a counter, say async_count. Increase it by one every time you start a request (inside you loop) and have the callback reduce it by one and check if zero has been reached - if so, all the callbacks have returned.

EDIT: Although, if I were the one writing this, I would chain the requests rather than running them in parallel - in other words, I have a queue of requests and have the callback check the queue for the next request to make.

Upvotes: 0

Related Questions