3

我听很多人说在 Node 中抛出错误是不好的做法,你应该通过 CommonJS 的回调语法手动处理它们:

somethingThatPassesAnError( function(err, value) {
    if (err) console.log("ERROR: " + err);
});

然而,我在多个单元测试框架(Mocha、Should.js、Gently)中发现,它们似乎希望throw在发生某些事情时出错。我的意思是,当然,您可以设计测试来检查变量的相等性并检查错误变量中的非空值,但用 Ryan Dahl 自己的话来说,“您应该编写框架以使正确的事情易于执行并且错事难做”。

那么给了什么?谁能解释为什么存在这种做法?require()如果找不到模块,我应该开始抛出致命异常吗?

4

4 回答 4

3

这是因为 nodejs 程序通常大量使用异步,因此在您的 try/catch 成功完成后经常会抛出错误。考虑这个人为的例子。

function foo(callback) {
  process.nextTick(function() {
    if (something) throw "error";
    callback("data");
  });
}

try {
  foo(function(data) {
    dosomething(data);
  });
} catch (e) {
  // "error" will not be caught here, as this code will have been executed
  // before the callback returns.
}

回调中的第一个参数是错误的典型节点模式避免了这个问题,提供了从异步代码返回错误的一致方式。

function foo(callback) {
  process.nextTick(function() {
    if (something) return callback("error");
    callback("data");
  });
}

foo(function(error, data) {
  if (error) return handleError(error);
  dosomething(data);
});
于 2013-01-19T04:09:03.873 回答
2

据我了解,反对在 JavaScript 中抛出异常的情况是由于大量使用了异步模式。当另一个堆栈发生错误时,您无法捕获它。在这些情况下,使用err参数作为回调的第一个参数。

我不认为这与说“永远不要扔任何东西”是一样的。如果我有同步代码,并且发生异常,我会抛出它。有不同的意见,但如果根本不涉及回调,我认为没有理由不使用throw.

于 2013-01-19T04:05:23.813 回答
1

对于这一点,我倾向于遵循Joyent 在 Node.js 中的错误处理的指导。过于简单的要点是实际上有两种类型的错误(操作错误和程序员错误),以及三种传递错误的方式(在事件发射器上发出错误事件,返回带有错误参数的回调非空,以及抛出错误)。

操作错误是您期望可能发生并且能够处理的错误,即。不一定是错误。程序员错误是代码本身的错误。如果您正在编写代码并且预计会出现错误,那么任何传递错误的模式都是有价值的。例如:

  • 如果错误发生在接受回调的异步函数内部,则使用惯用的 return callback(new Error('Yadda yadda yadda')) 是正确的解决方案(如果您无法处理函数中的错误)。
  • 如果错误发生在同步函数内部并且是一个破坏性问题(即,如果没有尝试过的操作,程序就无法继续),那么由于未捕获的抛出错误而爆炸是可以接受的。
  • 如果错误发生在同步函数中但可以处理,则该错误应该处理,否则应该抛出,也许父函数可以处理,也许不能。

就我个人而言,我倾向于只抛出我认为致命的错误,因此我的代码大多没有 try/catch 块(我什至将 JSON.parse 包装在一个如此定义的函数中:function jsonParseAsync(json, cb) { var out, err;尝试 { out = JSON.parse(json) } catch(e) { err = e }; return cb(err, out); } )。我还尽量避免使用 Promise,因为它们将 Promise 拒绝和抛出的错误混为一谈(尽管随着 Promise 变得越来越普遍,这变得越来越难)。相反,我倾向于将同步函数视为数学证明,因为如果它们是正确的,它们必须始终是正确的(因此同步函数中的错误应该会破坏整个程序,否则证明可能是错误的但仍然可用)。

于 2017-02-03T20:09:01.007 回答
0

我建议使用异常来处理严重错误,就像 require() 的工作方式一样。如果此功能导致 Node.js 行为不端,那么这是一个错误,我相信它会及时修复。

于 2013-01-19T04:05:59.887 回答