1

为什么下面的示例会在我的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) }
4

2 回答 2

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);

===

完整的东西会变成下面这样。请注意,我遵循 callback(err, result) 约定。

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); 
    });
};

最后,考虑使用(自定义)错误对象而不是字符串消息,谷歌它以解释原因。

于 2013-06-25T08:34:15.567 回答
1

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

在您调用的代码中

var user = isUser(login),

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

所以这句话if (!user) {变成了真的

为避免此错误,您应该放置isUser在回调函数中

意味着限制执行,直到并且除非您从函数获得响应

于 2013-06-25T06:20:58.733 回答