节点功能在Mongoose db find方法之前完成

时间:2013-06-25 05:14:03

标签: node.js mongodb database-connection mongoose

为什么下面的示例在 mongoose db查找函数完成之前返回节点中间件函数?我确信这是一个异步问题,但我有点迷失为什么。

中间件js文件

var mongoose = require('mongoose'),
    Schema = mongoose.Schema;

function isUser(login){
    var UsersSchema =  new Schema({
        user:       String,
        user_type:  String,
        password:   String,
        first_name: String,
        middle_name:String,
        last_name:  String,
        birth_date: Date,
        join_date:  Date
    });

    var UserModel = mongoose.model('users', UsersSchema);

    mongoose.connect('mongodb://localhost/identity');
    mongoose.model('users', UsersSchema);
    var db = mongoose.connection;
    db.on('error', console.error.bind(console, 'connection error: '));
    db.once('open', function cb () {    
        UserModel.findOne({'user': login}, function (err, user){
            if (err){ throw err; } 
            console.log('connected to user db and preformed lookup.');
            console.log(user);
            return user;
        });
    });
}

module.exports.authenticate = function (login, password, cb) {
    var user = isUser(login),
        msg;    
    console.log(user);
    if (!user) {
        msg = 'Invalid User';
        cb(null, msg);  
        return;
    }   
    if (user.password != password) {
        msg = 'Invalid Password';
        cb(null, msg);
        return;
    }
    cb(user, null); 
};

控制台输出

undefined
Login Failed! : Invalid User
connected to user db and preformed lookup.
{ _id: 51c8e16ce295c5b71ac6b229,
  user: 'bclark@themindspot.com',
  user_type: 'admin_master',
  password: 'enter',
  first_name: 'Brandon',
  middle_name: 'Laurence',
  last_name: 'Clark',
  birth_date: Fri Mar 19 1982 00:00:00 GMT-0800 (PDT),
  join_date: Wed Jun 26 2013 00:00:00 GMT-0700 (PDT) }

2 个答案:

答案 0 :(得分:2)

db.once和UserModel.findOne是异步函数,因此您提供了在完成时调用的匿名函数。如果你希望你的isUser函数“返回”这些异步函数的结果,你也必须使它使用回调。

替换 function isUser(login){function isUser(login, callback){

return user;callback(user)

还建议不要在异步代码中抛出错误,而是使用回调传递它们,类似于db.once和UserModel.find,如下所示:

删除 if (err){ throw err; } 并用上面的回调替换 callback(err, user);

当你在这里时,由于你不再对错误或用户做任何事情,你也可以打电话给UserModel.findOne({'user': login}, callback);

===

完整的事情将成为以下。请注意,我遵循回调(错误,结果)约定。

var mongoose = require('mongoose'),
    Schema = mongoose.Schema;

function isUser(login, callback){
    var UsersSchema =  new Schema({
        user:       String,
        user_type:  String,
        password:   String,
        first_name: String,
        middle_name:String,
        last_name:  String,
        birth_date: Date,
        join_date:  Date
    });

    var UserModel = mongoose.model('users', UsersSchema);

    mongoose.connect('mongodb://localhost/identity');
    mongoose.model('users', UsersSchema);
    var db = mongoose.connection;
    db.on('error', console.error.bind(console, 'connection error: '));
    db.once('open', function cb () {    
        UserModel.findOne({'user': login}, callback);
    });
}

module.exports.authenticate = function (login, password, cb) {
    var user = isUser(login, function(err, user) {
        if (err) {
            cb(err);
        }
        console.log(user);
        if (!user) {
            msg = 'Invalid User';
            cb(msg);  
            return;
        }   
        if (user.password != password) {
            msg = 'Invalid Password';
            cb(msg);
            return;
        }
        cb(null, user); 
    });
};

最后,考虑使用(自定义)错误对象而不是字符串消息,谷歌将其解释为什么。

答案 1 :(得分:1)

是的,这是一个异步问题。你可能知道node.js每个动作都有一个单独的线程

在你的代码中

你打电话

var user = isUser(login),

根据你应该返回isUser函数的结果,但执行给这个函数一个单独的线程,然后它继续下一个语句。 在下一个语句中,用户未定义,因为它没有从函数isUser

返回任何内容

所以声明if (!user) {变为真实

要避免此错误,您应将isUser放入回调函数

表示限制执行,除非您从函数

获得响应