在Node.js中暴露和组合错误的最佳方法是什么?

时间:2013-11-26 19:15:04

标签: javascript node.js error-handling

我正在编写一个与REST API对话的模块,并且由于REST API提供了良好的语义错误响应(例如403与503),我想将这些语义错误传达给调用者。

(编辑:我的意思是,调用者应该能够以编程方式理解错误的原因并采取相应的行动,例如显示相应的UI。)

对我来说最好的方法是什么?

  1. 为这些语义创建我自己的Error子类,例如: mymodule.ForbiddenErrormymodule.ServiceUnavailableError?然后,呼叫者将检查instanceof以获得语义。这在C#和Java等静态类型语言中最为常见。

  2. 添加例如标准mymoduleCode实例的Error属性,具有'Forbidden''ServiceUnavailable'等语义字符串。 Node.js本身就是这样做的,例如code: 'ECONNREFUSED'

  3. 其他方式?

  4. ==

    我现在正在编写另一个模块,它包装了第一个模块。我不想直接暴露内部模块的错误,但为了可调试性,编写/包装它们会很好。

    对我来说,最好的方法是什么呢?

    1. 添加例如引用内部模块internalError实例的Error个实例的Error属性。 C#和Java再次这样做。 (Exception#InnerException / Throwable#cause

    2. 其他方式?

    3. 我看到的大多数工具只显示stack个实例的Error属性,因此在这些情况下这些数据会丢失。是否存在已经存在的典型/传统方式?

5 个答案:

答案 0 :(得分:6)

您描述的用例现在肯定是Node未充分利用的用例。由于使用的惯例,它们往往是以下的混合物:

  1. 创建简单派生自Error构造函数的新错误类型。主要用于创建高级错误类别。您可以使用instanceof来区分错误类型,但这并不是非常简单的JavaScripty。
  2. 创建Java样式的错误子类型,将另一个错误作为构造函数参数,然后将其包装起来。如果你让子类型公开API,你基本上使用多态而不是直接调度来处理基于类型的错误。
  3. 通过Error构造函数创建语义上有用的错误消息。这是我倾向于使用很多的模式。
  4. 将属性附加到错误,这也非常常见。
  5. 创建一个解耦的错误处理API,可以从错误发生的任何地方调用它。这为您提供了一个集中所有代码的地方,这些代码可以确定您遇到的错误类型以及应该如何处理错误,并注入处理错误所需的任何依赖项。
  6. 这里真正的问题是这些都是临时机制,我不会说它们中的任何一个已达到临界质量。我认为这部分是由于异步性和JavaScript的结合使得很难正确并完全处理错误,因此建议通常在捕获有关错误的信息后关闭整个过程。

    这在处理预期错误方面做得不好,但我认为大多数错误都是由框架捕获的(例如Express错误处理程序)或者放入Node回调约定。简而言之,我认为这里有空间来定义一些惯例,因为最先进的技术并不是那么巧妙。

答案 1 :(得分:5)

发现这篇很棒的文章谈论这个:

http://www.joyent.com/developers/node/design/errors

此处粘贴太多,但在“特定建议”下,第2项至第5项解决了这个问题:

  
      
  1. 明确你的功能。
  2.   
  3. 对所有错误使用Error个对象(或子类),并实施Error合同。
  4.   
  5. 使用错误的name属性以编程方式区分错误。
  6.   
  7. 使用详细说明
  8. 的属性扩充Error对象   
  9. 如果您向调用者传递了较低级别的错误,请考虑将其换行。
  10.   

特别是,该文章链接到此模块以包装/撰写错误:

https://github.com/joyent/node-verror

我不确定我是否必须遵循这些完全约定 - 例如我认为拥有应用程序域code属性很有价值 - 但原则非常有用。

答案 2 :(得分:1)

编辑我是StackOverflow Node.js的新手。别人应该回答这个问题! : - )

如果您来自Java / C#欢迎使用JavaScript!我从未见过Node.js库使用instanceof来检查错误类型,但正如你所说的那样在静态语言中很常见。

话虽如此,通常只会创建新错误,并使用NodeJS的回调样式(err, response)进行回调。

我总是遇到来自其他模块的错误消息,知道它们来自何处以及创建包装错误消息是有帮助的,这些消息可能隐藏它实际上在我身上死亡的地方(我需要更多的东西来挖掘)。

创建一个可以处理字符串的休息错误消息(或者在您的情况下,响应无效)的函数的示例:

function myFunction(callback) {
    callRestAPI('http://someApi.com/request', function(errorString, jsonResponse) {
        if (errorString) { 
            callback(new Error("something wrong in myFunction! " + errorString)); 
        } else {
            callback(null, JSON.parse(jsonResponse));
        }
    });
}

在您的情况下,“errorString”检查基本上是响应(403/503),您可以将错误消息的结构设置为new Error( ... ),例如new Error('Failed! Got response 403!')

我可能错过了你的观点,也许别人可以更彻底。


重新阅读之后,你能发布你正在包装的模块吗?是节点请求吗?

答案 3 :(得分:1)

我对节点也很陌生,所以请稍等一下,但我会选择你的#2选项,添加一个属性。 (This is also suggested here)

这几乎是你最初的#2选项。如果错误处理程序只记录堆栈,而不是错误本身,那就是他们的错误。 :-)(严肃的,不知道你怎么做得更好)

答案 4 :(得分:0)

我只需将httpCode属性附加到错误对象即可。 KISS