Node.js错误抛出称为坏习惯,但对TDD至关重要

时间:2013-01-19 03:58:09

标签: javascript node.js unit-testing coding-style tdd

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

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

然而,我发现在多个单元测试框架(Mocha,Should.js,Gently)中,当发生某些事情时,他们似乎想要throw出错。我的意思是,当然,你可以设计你的测试来检查变量是否相等,并检查错误变量中的非空,但用Ryan Dahl自己的话来说,“你应该编写你的框架以使正确的事情变得容易,并且错误的事情很难做到。“

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

4 个答案:

答案 0 :(得分: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);
});

答案 1 :(得分:2)

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

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

答案 2 :(得分:1)

我倾向于遵循Joyent's Error Handling in Node.js对此的指导。过度简化的要点是,实际上有两种类型的错误(操作和程序员),以及三种传递错误的方法(在事件发射器上发出错误事件,将错误参数的回调返回为非null,并抛出错误) )。

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

  • 如果错误发生在接受回调的异步函数中,使用惯用的返回回调(new Error(' Yadda yadda yadda'))是一个正确的解决方案(如果你不能处理)功能中的错误。)。
  • 如果错误发生在同步函数内部并且是一个破坏问题(即程序无法在没有尝试的操作的情况下继续运行),那么吹嘘未被捕获的抛出错误是可以接受的。
  • 如果错误发生在同步函数中但可以处理,那么应该处理错误,否则应该抛出它,也许父函数可以处理它,也许不会。

就个人而言,我倾向于只抛出我认为致命的错误,因此我的代码大多没有try / catch块(我甚至将JSON.parse包装在一个如此定义的函数中:function jsonParseAsync(json,cb){var out ,错误;尝试{out = JSON.parse(json)} catch(e){err = e}; return cb(err,out);})。我也试图避免承诺,因为他们将承诺拒绝和抛出错误混为一谈(尽管随着承诺变得越来越普遍,这变得越来越难)。相反,我倾向于将同步函数视为数学证明,因为如果它们是正确的,它们必须始终是正确的(因此同步函数中的错误应该破坏整个程序,否则证明可能是错误的但仍然可用)。我的错误创建和检查几乎完全是针对错误输入和发出错误事件的断言,或者是惯用于处理异步错误。

答案 3 :(得分:0)

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