Nathan Campos
Nathan Campos

Reputation: 29497

Callback at MongoDB Operation With Node.js

For organization purposes I'm separating my source code into modules, for example I have the user module on my node.js app which is responsable for retrieving user information from a MongoDB database. I'm doing something like this:

var mongo = require("mongodb"),
    Server = mongo.Server,
    Db = mongo.Db;

var server = new Server("localhost", 27017, { auto_reconnect: true });
var db = new Db("users", server);

module.exports = {
    login: function(user, pass, callback) {
        var reg_result = null;

        db.open(function (err, db) {
            if(!err) {
                db.collection("users", function(err, collection) {
                    collection.findOne(
                        {
                            "username": user,
                            "password": pass
                        },
                        function(err, item) {
                            if(!err) {
                                reg_result = item;
                            } else {
                                reg_result = "error";
                            }
                        }
                    );
                });
            } else {
                reg_result = "error";
                console.log("ERROR: " + err);
            }
        });

        callback(reg_result);
    }
}

And executing it on my test script like this:

var user = require("./user.js");

user.log("test", "test", function(msg) {
    console.log(msg);
});

It does the database operation and retrieves the value, but every time it only returns null, when I don't initialize the reg_result variable it returns undefined. What should I do to correct this?

I debugged using console.log on the user.js and the item was outputted, but I want to have the callback so I can use the item on other sources, like my test script

Upvotes: 3

Views: 9253

Answers (1)

mindandmedia
mindandmedia

Reputation: 6825

You are calling the callback function right away, but going to the db takes time and is therefore done asynchronously. Instead, call your callback at the appropriate time using the result argument of the function passed as the last parameter to the .findOne() function. The callback should get an error argument and a result argument:

login: function(user, pass, callback) {
    db.open(function (err, db) {
        if(!err) {
            db.collection("users", function(err, collection) {
                collection.findOne(
                    {
                        "username": user,
                        "password": pass
                    },
                    function(err, item) {
                        if(!err) {
                            callback(null,item);
                        } else {
                            callback("error");
                        }
                    }
                );
            });
        } else {
            callback("error",null);
        }
    });
}


user.login("test", "test", function(err,msg) {
    if( err ) {
      //error occured above;
    } else {
      //success
      console.log(msg);
    }
});

this is just pulling the same pattern through that the mongodb-driver is using. hope it helps.

Upvotes: 6

Related Questions