为什么下面的示例在 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) }
答案 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
放入回调函数
表示限制执行,除非您从函数
获得响应