Node.js mongodb崩溃节点,在try catch中出现异常

Node.js mongodb崩溃节点,在try catch中出现异常,node.js,mongodb,coffeescript,Node.js,Mongodb,Coffeescript,这就在我的代码中产生了一个错误——这没关系,但是为什么即使我在这里有一个try-catch,我的nodejs程序也会崩溃呢 错误是: 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

这就在我的代码中产生了一个错误——这没关系,但是为什么即使我在这里有一个try-catch,我的nodejs程序也会崩溃呢

错误是:

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)
(因此它必须在更新调用中) 我正在寻找一种捕获错误的方法,我已经知道如何消除它。

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

如果我错了,您是否可以提供已编译的JavaScript代码

编辑

通常情况下,人们会更像这样处理错误(不使用try/catch):

您的
处理错误
可能已经可以执行此操作


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

啊,是的,您已经进入了异步代码领域。将回调传递到MongoDB调用(如
Item.update(…,callback)
中的原因是,MongoDB驱动程序是异步编写的。考虑这个(猫鼬代码):

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

var user = User.findOne({ name: 'joe' });
doSomethingElse();
上面的代码是异步的。
findOne
函数立即返回
doSomethingElse
甚至在从数据库检索用户之前就可以开始了。当然,我们仍然想对用户做一些事情,所以为了完成这一点,我们传入一个匿名函数作为回调函数。MongoDB驱动程序足够聪明,可以在检索完数据后调用该函数

将上述代码包装在try/catch中是毫无意义的,除非您怀疑
findOne
函数抛出异常(您不应该这样做。它会立即返回,还记得吗?)

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

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

我写了一篇完整的博客文章解释回调,以及另一种处理异步代码的方法,称为“承诺”,我认为这将有助于为您澄清一些事情:)


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

谢谢@Alex,它很好地解释了一切——但有些事情对我来说仍然是个谜。如果,如您所说,MongoDB“将自己的内部异步代码包装在一个try/catch中,它实际上将处理异常,然后调用您的回调,将错误作为第一个参数传入。”-为什么程序会因为一个相对无害的错误而完全崩溃,例如“MongoError:Mod on _idnot allowed”。这就是为什么我首先要尝试捕获的原因…我不希望我的程序崩溃!哎呀,我想是因为我重新抛出了错误,希望它被周围的try/catch捕捉到……这是一个死链接answer@StepanYakovenko给你:)
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")
  )
var user = User.findOne({ name: 'joe' });
doSomethingElse();
User.findOne({ name: 'joe' }, function (err, user) {
    if (err) return console.error(err);
    console.log('Do stuff with user... ;)');
});
doSomethingElse();
try {
    User.findOne({ name: 'joe' }, function (err, user) {
        throw new Error("Something went wrong...");
    });
} catch (err) {
    console.error(err);
}