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

时间:2013-11-15 22:53:52

标签: node.js mongodb 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)

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

错误是:

MongoError: Mod on _id not allowed

(所以它必须在更新通话中) 我正在寻找一种捕捉错误的方法,我已经知道如何摆脱它。

2 个答案:

答案 0 :(得分:7)

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

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

如果它像上面的代码那样构建了它的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();

上面的代码是异步的。 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返回后很久就发生了,并且您的程序超出了那个宝贵的try / catch。这就是您的回调函数收到err参数的原因。 MongoDB驱动程序知道如果在获取数据时发生了一些错误,那么抛出异常并将其调用就不错了。这是因为所有这些处理都是在后续的事件循环之后发生的,在几次迭代之前已经将try / catch留在了后面。

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

  

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

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

答案 1 :(得分:4)

也许我错了(因为我不知道Coffeescript),但我想问题是,你的try / catch在回调函数之外。捕获不会影响您的err ->,因此异常不会被您捕获,而是由node.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的周围异步函数仅在函数有编程错误时才有用(例如,没有正确检查输入)。