我不同意任何告诉你的人
永远不要在这些基于 Promise 的函数中抛出错误
在我看来,您应该在TypeError()指示程序员错误而不是操作错误时同步抛出。 p>
引用Joyent | Error Handling:
操作错误 代表正确编写的程序遇到的运行时问题。这些不是程序中的错误。 事实上,这些通常是其他问题 [...]
程序员错误 是程序中的错误。这些都是可以通过更改代码来避免的。它们永远无法正确处理(因为根据定义,相关代码已损坏)。
您的同事似乎无法区分这些类型的错误,而您编写的代码几乎应如此,除了使用通用的 Error() 而不是语义正确的TypeError().
为什么要关心差异?
您一开始说您正在为 AWS 开发工具包编写一个包装器。所以,从使用你的库的开发人员的角度来看,你认为他们更愿意调试一个在他们做错的地方立即抛出的程序,还是他们更愿意调试一个静默失败的程序,试图解决他们滥用你的 API 却没有通知他们错误的代码?
如果您认为第一个选项听起来更容易处理,那您就完全正确。在告诉程序员他们做错了什么时,您的程序应该始终尽可能透明。试图解决滥用问题会导致 API 出现错误,这些 API 具有未定义、未记录且只是简单的奇怪行为。
他们试图推荐我做什么?
举一个非常基本的例子(可能是不公平的比较,因为我不知道什么是 badInput),你的同事似乎在告诉你应该这样做:
try {
if (badInput) {
throw new Error('failed')
}
...
} catch (error) {
// expected error, proceed as normal
// ...except not really, you have a bug
}
而不是这个:
process.on('uncaughtException', function (error) {
// deal with programmer errors here and exit gracefully
})
if (badInput) {
throw new Error('failed')
}
try {
...
} catch (error) {
// deal with operational errors here and continue as normal
}
Node.js 运行时环境中的一些真实示例可以区分这些错误,甚至在异步函数中可以在 the chart here 中找到:
Example func | Kind of func | Example error | Kind of error | How to | Caller uses
| | | | deliver |
==========================================================================================
fs.stat | asynchronous | file not found | operational | callback | handle callback
| | | | | error
-------------+--------------+----------------+---------------+----------+-----------------
fs.stat | asynchronous | null for | programmer | throw | none (crash)
| | filename | | |
结论
我会让您决定您的特定问题是由于程序员错误还是操作错误造成的,但总的来说,给您的建议不是合理的建议,并鼓励有错误的程序试图就好像没有错一样继续进行。
TL;DR
在操作条件下预期返回Promise 的任何函数应在错误是由于错误引起时同步throw,并且在正确编写的程序中出现exogenous error 时应异步reject。
这反映了Joyent的官方推荐:
从程序员错误中恢复的最佳方法是立即崩溃。