Egidi
Egidi

Reputation: 1776

Javascript strange behavior, asynchronism issue?

I have the next code:

exports.getCommunities = function(user, callback)
{      //I am getting the communities for a user.
        community_users.find({'user':user}).sort({_id : 1 }).toArray(function(err, docs) {
            docs.sort
            var clas = [];
            //for each community, I need to find the country of that community and add it to each docs object. To do so, i call a getCommunityByName function that finds the community document in the communities mongodb collection by a given name.
            docs.forEach(function(entry,i) {
                clas.push(entry);
                getCommunityByName(entry.name, function(e, o){
                    if (o){
                        clas[i].country = o.country;
                        if (docs.length-1 == i) {callback(null,clas)}
                    } else { console.log('community-not-found: '+entry.name)}
                });

            });

        }); 
};

I am having strange behavior. Imagine docs is a 7 object array. I am obtaining a 7 positions array but a random number of them have the country key. Sometimes only 3 of them have the country key, sometimes are 5, sometimes 6...

I think that the if statement to call the callback is not waiting for every call to getCommunityByName and i don't know really why...

I need some light in this...

Regards,

Upvotes: 0

Views: 33

Answers (1)

James Thorpe
James Thorpe

Reputation: 32202

Assuming getCommunityByName performs an asynchronous request, it could be that the request for the final item is returning before some of the previous items, so it's calling the callback too soon. Rather than using i from the loop to decide when to call back, instead count down the returned requests and call the callback when they're all complete:

exports.getCommunities = function(user, callback)
{      //I am getting the communities for a user.
    community_users.find({'user':user}).sort({_id : 1 }).toArray(function(err, docs) {
        docs.sort
        var clas = [];
        //for each community, I need to find the country of that community and add it to each docs object. To do so, i call a getCommunityByName function that finds the community document in the communities mongodb collection by a given name.

        //initialise counter to number of items
        var counter = docs.length;
        docs.forEach(function(entry,i) {
            clas.push(entry);
            getCommunityByName(entry.name, function(e, o) {

                //request returned, decrement counter
                counter--;
                if (o){
                    clas[i].country = o.country;
                } else { console.log('community-not-found: '+entry.name)}
                if (counter == 0) {
                    //All requests returned, fire callback
                    callback(null, clas);
                }
            });

        });

    }); 
};

Upvotes: 1

Related Questions