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 包围异步函数。