Reputation: 347
I am having a synchronisation issue in Javascript. Code below. When I make the call to get mutual friends, although my function is still filling the array through the API callback, the printing of "Quite a bunch: 0"
happens before the printing of the - console.log(friendID +" -> " + mutualfriends.data.length);
I know this must be a callback / asynch issue but I have no idea how to deal with it. I'm filling the array for a reason - need it to be filled for the next part.
code:
function getMutualFriends(friendID)
{
//console.log(response.data[i].id);
try{
FB.api('/me/mutualfriends/'+friendID, function(mutualfriends) {
//console.log(mutualfriends);
//console.log(mutualfriends.data.length);
console.log(friendID +" -> " + mutualfriends.data.length);
mutualFriendsList.push([friendID,mutualfriends.data.length]);
});
}
catch(err){
console.log('error caught: ' +err);
}
}
function getFriendsList()
{
FB.getLoginStatus(function(response){
FB.api('/me/friends', function(response) {
for(i=0; i<response.data.length;i++)
{
var friendID = response.data[i].id;
console.log(friendID);
friendsList.push(friendID);
}
console.log('Interesting, we gathered: '+friendsList.length+' friends,');
console.log('lets check mutual friends now');
for(j=0; j<friendsList.length;j++)
{
getMutualFriends(friendsList[j]);
}
console.log('Quite a bunch: ' + mutualFriendsList.length);
});//friends
});
}
Upvotes: 0
Views: 153
Reputation: 598668
You'll probably want to turn your "post-condition" code into a callback.
So where you now have:
for(j=0; j<friendsList.length;j++)
{
getMutualFriends(friendsList[j]);
}
console.log('Quite a bunch: ' + mutualFriendsList.length);
You'll want something like:
for(j=0; j<friendsList.length;j++)
{
getMutualFriends(friendsList[j], function(mutualFriendsList) {
console.log('Quite a bunch: ' + mutualFriendsList.length);
});
}
When you set it up like this, your getMutualFriends
function can call the callback once it got the result:
function getMutualFriends(friendID, callback)
{
FB.api('/me/mutualfriends/'+friendID, function(mutualfriends) {
mutualFriendsList.push([friendID,mutualfriends.data.length]);
callback(mutualFriendsList);
});
}
This will do the callback once for every call to getMutualFriends
. If you want the callback to only trigger once for all friends, you'll need to expand the concept a bit further.
Update:
You could combine the above "per friend" callback with @RGDev's condition to detect the last friend:
for(j=0; j<friendsList.length;j++)
{
getMutualFriends(friendsList[j], function(mutualFriendsList) {
if (mutualFriendsList.length == friendsList.length) {
console.log('Quite a bunch: ' + mutualFriendsList.length);
}
});
}
Upvotes: 3
Reputation: 179
You could use a while loop to wait until the mutualFriendsList.length is equal to friendsList.length. which would mean that all of the ajax functions return functions had been fulfilled.
It would look something like:
while(mutualFriendsList.length != friendsList.length)
{
console.log("Still Waiting");
}
console.log('done')
// do your data processing
A little inelegant, but it should work
Upvotes: 0
Reputation: 1858
getMutualFriends is doing an async call on his own (by calling FB.api) so you cannot print the mutualFriendsList until it's done (actually, you are doing may calls to getMutualFiends so your mutualFriendsList won't be accurate until all of them finished their async processing).
Can't you rely on that collection to be async? I don't know what you are doing with that, but maybe (if you are drawing it in the screen by example) you can issue a redraw of that component every time the callback of FB.api('/me/mutualfriends/'+friendID, ...) is done.
I had a similar issue to you in the past, I solved it by using a backbone.js' collection instead of a simple javascript array. Then I bound a listener to the add event of the collection and print the qty of friends every time an object was added to it.
Good luck,
Upvotes: 0