mongodb在try catch中遇到异常崩溃的节点

fab*_*ous 2 mongodb node.js coffeescript

try
    p = req.params.name
    Item.update('name': p, req.body , {upsert: true}, (err) ->
      if err?
        throw err
      res.send("ok")
      )
  catch e
    handle_error(e, "Error salvando hoja de vida.", res)
Run Code Online (Sandbox Code Playgroud)

这在我的代码中产生了一个错误 - 这没关系,但是为什么我的nodejs程序崩溃,即使我在这里试试了?

错误是:

MongoError: Mod on _id not allowed
Run Code Online (Sandbox Code Playgroud)

(所以它必须在更新调用中)我特意寻找一种捕获错误的方法,我已经知道如何摆脱它.

Che*_*hev 7

啊,是的,你进入了异步代码的领域.将回调传递给MongoDB调用的原因Item.update(..., callback)是因为MongoDB驱动程序被编写为异步.考虑一下(猫鼬代码):

var user = User.findOne({ name: 'joe' });
doSomethingElse();
Run Code Online (Sandbox Code Playgroud)

如果它像上面的代码那样构建了它的API,那么整个应用程序将停止,直到User.findOne()从数据库返回结果.doSomethingElse()在检索用户之前,不会调用您的调用,即使您没有对user内部执行任何操作doSomethingElse.现在这是一个很大的问题,特别是在尽可能多地写入异步的节点中.看看以下内容:

User.findOne({ name: 'joe' }, function (err, user) {
    if (err) return console.error(err);
    console.log('Do stuff with user... ;)');
});
doSomethingElse();
Run Code Online (Sandbox Code Playgroud)

上面的代码是异步的.该findOne函数立即返回,doSomethingElse甚至可以在从数据库中检索用户之前开始.但是我们当然仍然希望对用户做一些事情,所以为了实现这个目的,我们传递一个匿名函数来用作回调.MongoDB驱动程序非常智能,可以在完成检索数据时调用该函数.

在try/catch中包含上面的代码是没有意义的,除非你怀疑findOne函数抛出一个异常(你不应该这样.它会立即返回记得?).

try {
    User.findOne({ name: 'joe' }, function (err, user) {
        throw new Error("Something went wrong...");
    });
} catch (err) {
    console.error(err);
}
Run Code Online (Sandbox Code Playgroud)

上面的错误仍会导致你的程序崩溃,因为它在findOne返回后发生了很长时间,并且你的程序超出了那个宝贵的try/catch.这就是你的回调函数接收err参数的原因.MongoDB驱动程序知道如果在获取数据时发生了一些错误,那么抛出异常并将其调用就不错了.这是因为所有这些处理都是在后续的事件循环之后发生的,在几次迭代之前已经将try/catch留在了后面.

为了解决这个问题,MongoDB驱动程序在try/catch中包装它自己的内部同步代码,它实际上将处理异常,然后调用你的回调传递错误作为第一个参数.这允许您检查该参数并处理回调中的任何错误.

我写了一篇完整的博客文章,解释了回调,以及另一种处理异步代码的方式,称为"promises",我认为这有助于为你澄清一些事情:) http://codetunnel.io/what-are-callbacks-and -promises

我希望这有助于回答你的问题.