0

我有一个带有用户对象的 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) { ... }是真的。

4

3 回答 3

3

callback(null, null)在迭代结果后立即调用。因此,如果您有一些结果 -callback将被调用两次:

  • 一个用于处理结果(将发送输出)
  • 迭代后第二次。

callback(null, null)只有在没有结果的情况下才应该打电话...

if (!users || users.toArray().length==0) callback(null, null);
于 2012-09-28T20:47:24.297 回答
0

让我们参考传递给 as 的函数和传递给collection.findas的函数(为清楚起见,我在下面的代码块中将它们标记为这样)。现在,问题是当您调用in时,循环继续运行,并且仍将继续测试结果中的所有剩余元素;此外,该函数仍未完成,将在循环完成后调用您的回调。你真的不能像我之前建议的那样在找到用户并调用之后,因为这只会终止单次迭代outerusers.eachinnercallback(null, user)innerusers.eachoutercallback(null, null)users.eachreturncallback(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);
});
于 2012-09-29T06:47:55.577 回答
0

你的回调仍然被执行:

for ( var key in obj ) {
  foo();
}

foo();

为什么您希望不调用第二个 foo() ?

你需要做 return foo(); 如果你不想继续下去。

于 2012-09-28T21:05:21.373 回答