mongodb在try catch中出现异常崩溃的节点
Posted
技术标签:
【中文标题】mongodb在try catch中出现异常崩溃的节点【英文标题】:mongodb crashed node with exception within try catch 【发布时间】:2013-11-29 11:49:57 【问题描述】: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
(所以它必须在更新调用中) 我正在专门寻找一种方法来捕获错误,我已经知道如何摆脱它。
【问题讨论】:
【参考方案1】:啊,是的,你已经进入了异步代码的领域。将回调传递给 MongoDB 调用(如 Item.update(..., callback)
)的原因是因为 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
返回之后很久,并且您的程序超出了宝贵的 try/catch。这就是您的回调函数接收err
参数的原因。 MongoDB 驱动程序知道,如果在获取数据时发生错误,那么抛出异常并称其为好是没有好处的。这是因为所有这些处理都发生在事件循环的后续行程中,在几次迭代之前将您的 try/catch 抛在后面。
为了解决这个问题,MongoDB 驱动程序将它自己的内部同步代码包装在一个 try/catch 中,它实际上将在其中处理异常,然后它调用您的回调,将错误作为第一个参数传入。这使您可以检查该参数并处理回调中的任何错误。
我写了一篇完整的博客文章来解释回调,以及另一种处理异步代码的方法,称为“承诺”,我认为它会帮助你澄清一些事情:) http://codetunnel.io/what-are-callbacks-and-promises
我希望这有助于回答您的问题。
【讨论】:
感谢@Alex,它很好地解释了一切——但对我来说,有些事情仍然是个谜。如果,如您所说,MongoDB“将自己的内部异步代码包装在一个 try/catch 中,它实际上将处理异常,然后它调用您的回调,将错误作为第一个参数传递。” - 为什么程序会因为一个相对无害的错误而完全崩溃,例如“MongoError: Mod on _id not allowed”。这就是为什么我首先尝试捕获的原因......我不希望我的程序崩溃! oops - 我猜是因为我重新抛出错误,期望它被周围的 try/catch 捕获...... 答案中有死链接 @StepanYakovenko 给你 :) codetunnel.io/what-are-callbacks-and-promises【参考方案2】:也许我错了(因为我不知道 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 中编程时,我仅将 try/catch 用于JSON.parse
,或者如果我有很多未经检查的输入,这些输入可能有错误的类型或可能为 null,我也是懒得手动检查所有输入。仅当函数存在编程错误(例如,未正确检查您的输入)时,使用 try/catch 包围异步函数才有用。
【讨论】:
以上是关于mongodb在try catch中出现异常崩溃的节点的主要内容,如果未能解决你的问题,请参考以下文章
“崩溃了?不可能,我全 Catch 住了” | Java 异常处理