我有一个带有用户对象的mongob。这是架构:
{
"_id": {
"$oid": "50658c835b821298d3000001"
},
"email": "admin",
"password": "admin",
"id": 1
}
我写了一个简单的演示(只有主要部分):
function findByEmail(email, callback) {
db.collection("users", function(err, collection) {
collection.find({}, function(err, users) {
users.each(function(err, user) {
if (user) {
if (user.email === email) {
//for a case, is we found user - return it
callback(null, user);
}
}
});
//for a case, is we didn't find user - return null
callback(null, null);
});
});
}
测试路线:
app.get('/test',function(req,res){
findByEmail("admin", function(err, user){
res.send(user);
})
})
在推出localhost:3000 / test后我得到了
Error: Can't set headers after they are sent.
如果我评论第callback(null, null);
行,我就不会收到此错误。似乎回调工作......两次!怎么会这样?我认为,如果我if (user.email === email) { ... }
有效并且callback(null, user);
已启动,则函数findbyEmail
会将<user>
返回到app.get
,但回调会工作两次(对于callback(null, null);
即使if (user.email === email) { ... }
成立也是如此。
答案 0 :(得分:3)
您在迭代结果后立即调用callback(null, null)
。因此,如果您有一些结果 - callback
将被调用两次:
如果没有结果,您只能致电callback(null, null)
if (!users || users.toArray().length==0) callback(null, null);
答案 1 :(得分:0)
你的回调仍然被执行:
for ( var key in obj ) {
foo();
}
foo();
为什么你不期望第二个foo()不被调用?
你需要做返回foo();如果你不想继续前进。
答案 2 :(得分:0)
让我们将您传递给collection.find
的功能称为outer
,将传递给users.each
的功能称为inner
(我已在代码块中将其标记为下面为了清楚起见)。现在,问题是当你在callback(null, user)
中调用inner
时,users.each
循环继续运行,并且仍将继续测试结果中的所有剩余元素;此外,outer
函数仍未完成,并将在callback(null, null)
循环完成后调用users.each
回调。在找到用户并按照我之前的建议调用return
之后,你真的不能只callback(null, user)
,因为这只会终止users.each
循环的单次迭代并继续下一个以及所有剩余的元素;您需要定义一个标志,指示您是否已经找到该记录:
collection.find({}, function outer(err, users) {
var found = false;
users.each(function inner(err, user) {
if (user && !found) {
if (user.email === email) {
//for a case, is we found user - return it
callback(null, user);
found = true;
}
}
});
//for a case, is we didn't find user - return null
if (!found) {
callback(null, null);
}
});
另请注意,您可以通过mongo中的电子邮件完全搜索用户记录,并用以下内容替换整个逻辑:
collection.find({ email: email }, function(err, users) {
callback(null, users.length? users[0]: null);
});