node.js:抛出错误但未被捕获

5
我有一个API,使用swagger与node.js上的express集成,并定义了以下资源。在检查(!req.params.id)时抛出的swagger错误被swagger的默认错误处理程序捕获。从mongoDB删除调用的回调函数中抛出的错误没有被捕获,给我以下错误。该错误似乎与回调函数的作用域/顺序有关,作为一个新手,我希望能得到如何正确处理此问题的建议,同时保持异步性。-谢谢
exports.remove = {
    'spec' : {
      "collapsed...for...brevity..." : "...",
      "params" : [ {
        "paramType" : "path",
        "name" : "id",
        "collapsed...for...brevity..." : "...",
      }],
      "errorResponses" : [ swe.notFound('id'), swe.invalid('id') ],
      "nickname" : "remove"
    },
    'action' : function(req, res) {

      if (!req.params.id) {
        throw swe.invalid('id');   // THIS ERROR IS CAUGHT
      }

      req.coll.remove({_id : req.coll.id(req.params.id)}, function(e, result) {
        if (e) {
          throw swe.invalid('collection');   // THIS ERROR IS NOT CAUGHT
        }

        res.send({msg : 'success'});
      });
    }
  };

您所说的“未捕获”是指它未被某个自定义错误处理程序捕获,还是它在控制台中未抛出错误? - adeneo
异步处理程序抛出的异常无法轻松捕获。那么修复导致抛出异常的问题呢? - Pointy
3个回答

6

在异步回调中抛出的异常会传递给回调的调用者,而不是你周围的代码。因此,req.coll.remove 代码接收到异常(未处理),从而导致应用程序崩溃。

相反,您需要让您的删除 action 函数接受一个回调参数,以便它可以将错误信息传递回调用者。

这就是为什么在 node.js 代码中很少使用异常,而回调是标准的原因。


5

规则 1. 不要在回调函数中抛出异常。最好根本不要抛出异常。只有在想要让进程崩溃时才抛出异常。如果需要将错误传递给调用者,请使用callback(err)。如果您在 connect/express 中间件范围内,则还可以使用next(err)

规则 2. 如果仍然有异常,并且您想捕获它,请使用domains。考虑到规则1,这样可以捕捉到非常意外的异常,所以您必须尽快关闭进程。


1
JohnnyHK的回答也是正确的,但vkurchatkin还指出了我将要研究的领域。 - rogodeter

1

不要使用回调函数,而是使用Promise,并在Promise链中抛出异常...

var P = require('bluebird');

// ...

return new P(function(resolve, reject) {
  req.coll.remove({_id : req.coll.id(req.params.id)}, function(e, result) {
    if (e) {
      reject(swe.invalid('collection'));   // THIS ERROR will be CAUGHT
    }
    resolve(res.send({msg : 'success'}));
  });
})
.catch(function(err) {
  throw err;
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接