在Node.js中公开和组合错误的最好方法是什么?
我正在编写一个与REST API交谈的模块,由于REST API提供了很好的语义错误响应(例如403与503),我想将这些语义错误传递给调用者。
(编辑:我的意思是,调用者应该能够以编程方式了解错误的原因,并采取相应的行动,例如显示适当的用户界面。)
对我来说最好的办法是什么?
-
为这些语义创build我自己的
Error
子类,例如mymodule.ForbiddenError
,mymodule.ServiceUnavailableError
? 然后调用者会检查instanceof
来派生语义。 这在静态types语言(如C#和Java)中最为典型。 -
将例如
mymoduleCode
属性添加到标准的Error
实例,使用语义string,如'Forbidden'
或'ServiceUnavailable'
。 Node.js自己做这个,例如code: 'ECONNREFUSED'
。 -
其他方式?
==
我正在编写另一个模块,它包装了第一个模块。 我不想直接暴露内部模块的错误,但是为了可debugging性,编写/包装它们会很好。
对我来说最好的办法是什么?
-
将例如
internalError
属性添加到引用内部模块的Error
实例的Error
实例中。 再次C#和Java这样做。 ( Exception#InnerException / Throwable#cause ) -
其他方式?
但是我见过的大多数工具只显示Error
实例的stack
属性,所以这些数据在这些情况下会丢失。 有没有一个典型的/传统的方式已经存在?
你所描述的用例现在是由Node明显不足的用例。 由于有使用的惯例,它们往往是一些混合物:
- 创build从Error构造函数派生的新的错误types。 主要用于创build高级错误类别。 您可以使用
instanceof
来区分错误的types,但是这并不感觉JavaScripty。 - 创build另一个错误作为构造函数参数,然后包装它们的Java风格的错误子types。 如果你让子types暴露一个API,你基本上是使用多态而不是直接调度来处理基于types的错误。
- 通过Error构造函数创build语义有用的错误消息。 这是我倾向于使用很多的模式。
- 将属性附加到错误,这也是非常普遍的。
- 创build一个分离的error handlingAPI,可以从错误发生的地方调用。 这给你一个地方集中所有的代码,找出你有什么样的错误,你应该怎么做,并注入你需要处理的错误的任何依赖关系。
这里真正的问题是这些都是临时性的机制,我不会说它们中的任何一个达到临界点。 我认为这部分是因为asynchronous性和JavaScript的组合使得正确和完全地处理错误变得困难,所以build议通常在捕获关于错误的信息之后closures整个过程。
这对于处理预期的错误并不是很好,但是我认为这些错误中的大部分都是由框架捕获的(例如,Expresserror handling程序),或者放到Nodecallback约定中。 总之,我认为在这里有空间来定义一些约定,因为艺术的状态不是那么巧妙。
发现这篇关于这个伟大的文章:
http://www.joyent.com/developers/node/design/errors
在这里粘贴太多,但在“具体build议”下,第2项至第5项解决这个问题:
- 清楚你的function在做什么。
- 对所有错误使用
Error
对象(或子类),并实现Error
合同。- 使用错误的
name
属性以编程方式区分错误。- 使用解释详细信息的属性来增加
Error
对象- 如果您向调用者传递较低级别的错误,请考虑换行。
特别是,这篇文章链接到这个模块的包装/撰写错误:
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
属性附加到错误对象。 吻