Reputation: 7732
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
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
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
Reputation: 38801
You can use the async
module for that.
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