Not reaching the end of the function

Problem

I have a JS function which adds a UserArticle to the DB (using mongoose and NodeJS). The problem is that it doesn't reach the end.

I mean, I have tried to determine at which place the majority of time reaches and is before the Provider.findOne or, before User.find.


var insertUserArticleToAllSubscribers = function (base_ua, providerId) {
    var Provider = mongoose.model('Provider');
    var User = mongoose.model('User');
    var UserArticle = mongoose.model('UserArticle');
    Provider.findOne({"twitter_id": providerId}, function (err, provider) {
        if (err) {
            console.log(err);
            return;
        }
        if (provider) {
            User.find({"subscribed": provider._id}, function (err, users) {
                if (err) {
                    console.log (err);
                    return;
                }
                if (users) {
                    for (i in users) {
                        var ua = new UserArticle ({"user": users[i], "article":base_ua.article, "place":base_ua.place, "read":0, "starred":0});
                        ua.save(function (err) {
                            if (err) console.log(err);
                            logAddedArticle(ua._id, users[i]);
                            console.log("ArticleAdded!: " + ua._id);            

                        });

                    }
                } else {
                    console.log("No users");
                }
            })
        }
    })
}

I don't understand why it doesn't reach the end of the function without throwing any error. Is there a bug in this piece of code?

Well, in fact, it sometimes reaches the end of the function but almost always it doesn't.

Thank you

Problem courtesy of: Francesc

Solution

Assuming that Provider.findOne() is actually invoking the callback (hopefully a safe assumption), then you probably need an else on the first if( provider ) call.

Right now you have this logical structure:

function (...) {
    Provider.findOne(..., function (...) {
        if (err) { ... }
        if (provider) {
            User.find(..., function(...) {
                if (err) { ... }
                if (users) { ... } 
                else { ... }
            })
        }
    })

You will probably get a result if you change it to this:

function (...) {
    Provider.findOne(..., function (...) {
        if (err) { ... }
        else if (provider) {                   // MAKE THIS AN ELSE IF
            User.find(..., function(...) {
                if (err) { ... }
                else if (users) { ... }        // MAKE THIS AN ELSE IF!
                else { ... }
            })
        }
        else {                                 // ADD THIS ELSE!
            console.log('findOne() found nuttin :(');
        }
    })
Solution courtesy of: Kato

Discussion

There is currently no discussion for this recipe.

This recipe can be found in it's original form on Stack Over Flow.