MongoDB崩溃的节点在Try Catch中异常


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)

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

错误是:

MongoError: Mod on _id not allowed

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

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

var user = User.findOne({ name: 'joe' });
doSomethingElse();

如果它像上面的代码一样构建了它的API,那么你的整个应用程序将停止,直到User.findOne()从数据库返回结果。在检索用户之前,不会调用您的doSomethingElse()调用,即使您没有对doSomethingElse中的user执行任何操作。这些天这是一个很大的禁忌,尤其是在已经编写为尽可能异步的节点中。请看以下内容:

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

上面的代码是异步的。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);
}

上述错误仍然会使您的程序崩溃,因为它发生在findOne返回很久之后,并且您的程序超出了宝贵的尝试/捕获。这就是您的回调函数收到err参数的原因。MongoDB驱动程序知道,如果在获取数据时发生一些错误,则抛出异常并称其为好是没有好处的。这是因为所有这些处理都是在事件循环的后续行程中发生的,在几次迭代之前就将您的 try/catch 抛在了后面。

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

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

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

也许我错了(因为我不知道 Coffeescript),但我想问题是,你的 try/catch 在回调函数之外。捕获不会影响您的err ->因此异常不是由您捕获,而是由节点.js捕获。

如果我错了,你能提供编译好的JavaScript代码吗?

编辑

通常人们会像这样处理错误(没有try/catch):

Item.update('name': p, req.body , {upsert: true}, (err) ->
  if err?
    log.error('error updating Item name=' + name)
    res.status(500).end()
    return
  res.send("ok")
  )

可能你的handle_error已经这样做了。

在node.js中编程时,我只对JSON.parse使用try/catch,或者如果我有很多未经检查的输入,这些输入可能具有错误的类型或可能是null,并且我懒得手动检查所有输入。仅当函数存在编程错误(例如,未正确检查输入)时,才有用 try/catch 包围异步函数。

最新更新