metalaureate
metalaureate

Reputation: 7732

Node.js how to _.each internal callbacks synchronously

I'm fairly new to node.js, and I can't figure out how to control the program flow so that my function waits for an Underscore _.each() block with internal callbacks. I'd really like to avoid a heinous callback stew. This block is in a chain already controlled by nimble's .series([])

function (callback) { //get common friends    
    _.each(User.friends, function (friend) { //I NEED THE FLOW TO WAIT TIL THIS COLLECTION HAS ITERATED AND ALL THE CALLBACKS ARE COMPLETE
        request.get({
            url: 'https://graph.facebook.com/me/mutualfriends/' + friend.id + '?access_token=' + User.accessToken,
            json: true
        }, function (error, response, body) { //NEED TO WAIT TIL THESE ARE ALL COMPLETED
            if (!error && response.statusCode == 200) {
                console.log("common friends", body.data);

            } else {
                console.log(error);
            }
        });

    }, this);

    callback(); //Nimble's serialization callback fires immediately
},

I've tried a suggestion below to use async.each, but I can't get the iteration completion callback to fire, to tell nimble's .series function to continue to the next block.

async.each(User.friends, function(friend) {
        request.get({
        url: 'https://graph.facebook.com/me/mutualfriends/'+friend.id+'?access_token=' + User.accessToken,
        json: true
        }, function (error, response, body) { //NEED TO WAIT TIL THESE ARE ALL COMPLETED
            if (!error && response.statusCode == 200) {
                console.log("common friends",body.data);

            } else {
                console.log(error);
            }
        });


    },function(err) {console.log('Final callback');callback();}); //THIS CALLBACK DOESN'T FIRE - NIMBLE JUST SITS AND WAITS

Upvotes: 0

Views: 3578

Answers (3)

Kevin Simper
Kevin Simper

Reputation: 1697

Your code was close to being right. You have to pass and use the callback function, else Async do not know when to call the final callback.

async.each(User.friends, function(friend, cb) {
    request.get({
        url: 'https://graph.facebook.com/me/mutualfriends/' + friend.id + '?access_token=' + User.accessToken,
        json: true
    }, function(error, response, body) { //NEED TO WAIT TIL THESE ARE ALL COMPLETED
        if (!error && response.statusCode == 200) {
            console.log("common friends", body.data);
            cb(null);
        } else {
            console.log(error);
            callback(error);
        }
    });
}, function(err) {
    console.log('Final callback', err);
    callback();
});

Upvotes: 1

TaeHee Kim
TaeHee Kim

Reputation: 83

try this.

function (callback) { //get common friends  
 var completeCount = 0;  
  _.each(User.friends, function (friend) { 
    request.get({
        url: 'https://graph.facebook.com/me/mutualfriends/' + friend.id + '?access_token=' + User.accessToken,
        json: true
    }, function (error, response, body) { //NEED TO WAIT TIL THESE ARE ALL COMPLETED
        if (!error && response.statusCode == 200) {
            console.log("common friends", body.data);

        } else {
            console.log(error);
        }

        completeCount++;

        // complete count check           
        if( completeCount === User.friends.length ){
           callback()
        }
    });

  }, this);    
},

Upvotes: 1

Daniel
Daniel

Reputation: 38801

You can use the async module for that.

async.each

Your code should look something like this:

async.each(User.friends, function(friend, cb) {
  var req = {
    url: 'https://graph.facebook.com/me/mutualfriends/'+friend.id+
      '?access_token='+User.accessToken,
    json: true
  };
  request.get(req, function(err,response,body) {
    if(err) { console.log(err); cb(true); return; }
    console.log("common friends",body.data);
    // each function call has to finish by calling `cb`
    cb(false);
  });
},
function(err) {
  if(err) return;
  console.log('Final callback');
  callback(); // here is your final callback
}
);

Upvotes: 2

Related Questions