在Node.js中公开和组合错误的最好方法是什么?

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

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

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

  1. 为这些语义创build我自己的Error子类,例如mymodule.ForbiddenErrormymodule.ServiceUnavailableError ? 然后调用者会检查instanceof来派生语义。 这在静态types语言(如C#和Java)中最为典型。

  2. 将例如mymoduleCode属性添加到标准的Error实例,使用语义string,如'Forbidden''ServiceUnavailable' 。 Node.js自己做这个,例如code: 'ECONNREFUSED'

  3. 其他方式?

==

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

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

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

  2. 其他方式?

但是我见过的大多数工具只显示Error实例的stack属性,所以这些数据在这些情况下会丢失。 有没有一个典型的/传统的方式已经存在?

你所描述的用例现在是由Node明显不足的用例。 由于有使用的惯例,它们往往是一些混合物:

  1. 创build从Error构造函数派生的新的错误types。 主要用于创build高级错误类别。 您可以使用instanceof来区分错误的types,但是这并不感觉JavaScripty。
  2. 创build另一个错误作为构造函数参数,然后包装它们的Java风格的错误子types。 如果你让子types暴露一个API,你基本上是使用多态而不是直接调度来处理基于types的错误。
  3. 通过Error构造函数创build语义有用的错误消息。 这是我倾向于使用很多的模式。
  4. 将属性附加到错误,这也是非常普遍的。
  5. 创build一个分离的error handlingAPI,可以从错误发生的地方调用。 这给你一个地方集中所有的代码,找出你有什么样的错误,你应该怎么做,并注入你需要处理的错误的任何依赖关系。

这里真正的问题是这些都是临时性的机制,我不会说它们中的任何一个达到临界点。 我认为这部分是因为asynchronous性和JavaScript的组合使得正确和完全地处理错误变得困难,所以build议通常在捕获关于错误的信息之后closures整个过程。

这对于处理预期的错误并不是很好,但是我认为这些错误中的大部分都是由框架捕获的(例如,Expresserror handling程序),或者放到Nodecallback约定中。 总之,我认为在这里有空间来定义一些约定,因为艺术的状态不是那么巧妙。

发现这篇关于这个伟大的文章:

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

在这里粘贴太多,但在“具体build议”下,第2项至第5项解决这个问题:

  1. 清楚你的function在做什么。
  2. 对所有错误使用Error对象(或子类),并实现Error合同。
  3. 使用错误的name属性以编程方式区分错误。
  4. 使用解释详细信息的属性来增加Error对象
  5. 如果您向调用者传递较低级别的错误,请考虑换行。

特别是,这篇文章链接到这个模块的包装/撰写错误:

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

我不确定我需要遵循这些确切的约定 – 例如,我看到有一个应用程序域code属性的价值 – 但原则是非常有帮助的。

编辑我是StackOverflow Node.js的新手。 其他人应该回答这个问题! 🙂

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

这就是说,创build新的错误和使用NodeJS的callback风格(err, response)进行callback是很典型的。

我总是遇到来自其他模块的错误消息,知道它们来自哪里,创build包裹的错误消息可能会隐藏它实际上死在我身上(我需要更多的东西来挖掘)。

创build一个函数可以处理string(或在你的情况下,无效的响应)的rest错误消息的一个例子:

 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!')

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


重新阅读后,你可以发布你正在包装的模块。 它是节点请求吗?

我对节点也很新颖,所以拿一点盐,但是我会select你的#2选项,添加一个属性。 (这也是在这里build议的) 。

这几乎是你原来的#2选项。 如果error handling程序只是logging堆栈,而不是错误本身,那是他们的错。 :-)(严重,不知道你怎么能做得更好)

我只是将一个httpCode属性附加到错误对象。 吻