NodeJS崩溃:当找不到文档时,Mongoose findById()不会抛出错误

时间:2016-05-15 03:28:31

标签: node.js mongodb express mongoose crash

我试着研究这个问题的原因;这很可能是我对Mongoose工作方式的误解。我正在尝试用REST风格创建一个CRUD后端。 GET,PUT,POST似乎都有效。但是,我对DELETE动词的问题有点不知所措。

问题

我和Postman一起向mongo输入了一些假数据,一切顺利。所以我复制了我的一个记录的_id字段并尝试删除。当我发送DELETE请求时,成功消息通过,记录确实已从mongo中删除。但是,在删除其他记录后,我决定尝试删除包含已删除文档的_id的记录。

我向'api / brothers / 57280602953cff031f21ad9c'发送了DELETE请求

原来NodeJS崩溃了!

以下是相关的服务器代码:

// DELETE a brother by id
app.delete('/api/brothers/:id', function(req, res) {

    Brother.findById(req.params.id, function(err, brother) {

      if (err) {
        // error finding brother
        res.json(err);

      } else {

        // remove record
        brother.remove(function(err, brother) {

          if (err) {
            // error removing!
            res.send(err);
          } else {

            // successful DELETE!
            res.json({
              message : "successfully deleted",
              brother : brother
            });
          }

        });
      }

    });


  });

Nodejs崩溃,我的控制台窗口返回以下内容:

TypeError: Cannot read property 'remove' of null
[nodemon] app crashed - waiting for file changes before starting...

为什么Mongoose没有抛出错误?

根据我的理解,没有抛出错误,因为如果它被抛出,我的if语句就会执行并将错误返回给用户。如果我在url中输入了一个伪造的id,那么我会收到一个错误,但是如果我粘贴了一个我已经删除的记录的_id,则不会抛出错误,并且执行会移动到else块,并且继续删除不存在的文档。甚至.remove()似乎都没有发现错误......服务器崩溃了。

所以......我的问题是为什么?是否与Mongo施放_id有关?为什么不抛出错误?为什么服务器崩溃。

解决方案......

如果我修改if语句不仅要捕获错误,还要检查是否存在从brother函数返回的findById(),则会返回错误避免了用户和灾难:

if (err || !brother) {
  // THIS WORKS
  res.json(brother);

 } else { ...

再次......为什么?为什么如果brother obj为null,Mongoose甚至会尝试删除文档?为什么服务器会崩溃?

//我正在使用Express 4.13.4和Mongoose 4.4.12

感谢您的帮助,并原谅任何新手的无知。

3 个答案:

答案 0 :(得分:4)

你得到的是一个Javascript错误,而不是一个Mongoose错误,你试图在null上调用一个方法。 foo = null; foo.bar();会产生同样的错误。

找到0文件不是错误,找到了查找的动作,但找到了0件事。

Mongoose有一个辅助函数findOneAndRemove,你应该使用它,编写更少的代码,减少头痛:

app.delete('/api/brothers/:id', function(req, res) {
    Brother.findOneAndRemove({ _id: req.params.id }, function(err, brother, res) {

    });
});

答案 1 :(得分:1)

如果发生无法连接数据库,无效身份验证等事件,则抛出

err。但对于查询,只要查询正确,它就会抛出任何错误。在您的查询返回0行的情况下,它只会使用null调用您的回调,因此您可能需要在使用brother之前进行检查。

答案 2 :(得分:0)

在使用删除之前,你必须检查兄弟是否存在,如果找不到项目,moongoose将不会返回错误。

if(!brother){
   return res.status(400).send('Item Not Found')   
}