在Mongoose db查找方法之前完成Nodefunction

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

中间件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) } 

db.once和UserModel.findOne是asynchronous函数,因此为什么要提供一个匿名函数,在完成时调用它们。 如果你想让你的isUser函数“返回”这些asynchronous函数的结果,你还必须使用callback函数。

replacefunction isUser(login){function isUser(login, callback){

return user;callback(user)

还build议不要在asynchronous代码中抛出错误,而是用callback函数传递它们,就像db.once和UserModel.find所做的那样:

if (err){ throw err; } if (err){ throw err; }并用callback(err, user);replace上面的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); }); }; 

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

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

在你的代码中你打电话

var user = isUser(login),

根据你它应该返回isUser函数的结果,但执行给这个函数一个单独的线程,它会继续下一个语句。 因为在下一个语句中,用户是未定义的,因为它不会从函数isUser返回任何东西

所以语句if (!user) {成为true

为了避免这个错误,你应该把isUser放在一个callback函数中

意味着限制执行,除非你得到函数的响应