Javascript 从服务类抛出与返回错误

Javascript 从服务类抛出与返回错误,javascript,node.js,Javascript,Node.js,从服务类抛出错误和返回错误之间是否有实质性的区别 类产品服务{ 异步getProduct(id){ const product=await db.query(`…`) 如果(!产品){ 抛出新ProductNotFoundError() } 退货 } //VS 异步getProduct(id){ const product=await db.query(`…`) 如果(!产品){ 返回{ 数据:空, 错误:新产品NotFoundError() } } 返回{ 错误:null, 数据:产品 } }

从服务类抛出错误和返回错误之间是否有实质性的区别

类产品服务{
异步getProduct(id){
const product=await db.query(`…`)
如果(!产品){
抛出新ProductNotFoundError()
}
退货
}
//VS
异步getProduct(id){
const product=await db.query(`…`)
如果(!产品){
返回{
数据:空,
错误:新产品NotFoundError()
}
}
返回{
错误:null,
数据:产品
}
}
}
在本例中,如果找不到产品,我想发出一条错误消息(假设返回null是不够的,可能我还需要提供其他信息来说明找不到产品的原因)

作为一般设计原则,是否有首选方法,两种方法是否都有实质性的优点/缺点

我一直在做
抛出新错误的
示例,但随后代码中出现了try/catch或.then/.catch语句,这使得推理变得有些困难

我特别不喜欢抛出错误的地方是。。这并非意外。显然,我希望可能找不到产品,所以我添加了一条逻辑来处理该部分。然而,它最终被调用者以相同的方式接收,例如,一个TypeError被接收。一个是预期的域错误,另一个是意外的异常

在第一个场景中,如果我从每个服务返回一个具有
data
error
属性的对象(或者我可以返回一个具有类似
isError
isSuccess
getData
方法的对象),我至少可以相信我的代码不会引发异常。如果发生了错误,那么根据定义,它将是意外的,并被全局错误处理程序(例如,express中间件)捕获

从服务类抛出错误和返回错误之间是否有实质性的区别

差别很大<异步函数中的code>throw
导致从任何
async
函数返回的承诺被拒绝,该异常作为拒绝原因。返回值将成为承诺的
已解决的

因此,最大的区别在于
async
函数返回的承诺是用一个值来解析的,还是用一个原因来拒绝的

作为一般设计原则,是否有首选方法,两种方法是否都有实质性的优点/缺点

大多数人在异常情况下使用承诺拒绝,在这种情况下,调用方通常希望停止其正常代码流,并追求不同的代码路径,并对可能继续正常代码流的内容使用返回值。想想连锁承诺:

x().then(...).then(...).catch(...)
如果由于某些严重的问题被发现,情况应该立即转到
.catch()
,那么抛出/拒绝在
x()
中最有意义。但是,如果该条件只是典型地处理并继续正常执行,那么您只需要返回一个值,而不是抛出/拒绝

因此,您尝试将
x()
设计为最容易达到预期用途。在数据库中找不到产品是一种预期的可能情况,但调用者也可能希望中止其所处的逻辑流,但对该情况的处理肯定不同于数据库中的实际错误

作为一个参考示例,您会注意到大多数数据库不会将在查询中查找失败视为错误。这只是“找不到”的结果

从服务类抛出错误和返回错误之间是否有实质性的区别

差别很大<异步函数中的code>throw
导致从任何
async
函数返回的承诺被拒绝,该异常作为拒绝原因。返回值将成为承诺的
已解决的

因此,最大的区别在于
async
函数返回的承诺是用一个值来解析的,还是用一个原因来拒绝的

作为一般设计原则,是否有首选方法,两种方法是否都有实质性的优点/缺点

大多数人在异常情况下使用承诺拒绝,在这种情况下,调用方通常希望停止其正常代码流,并追求不同的代码路径,并对可能继续正常代码流的内容使用返回值。想想连锁承诺:

x().then(...).then(...).catch(...)
如果由于某些严重的问题被发现,情况应该立即转到
.catch()
,那么抛出/拒绝在
x()
中最有意义。但是,如果该条件只是典型地处理并继续正常执行,那么您只需要返回一个值,而不是抛出/拒绝

因此,您尝试将
x()
设计为最容易达到预期用途。在数据库中找不到产品是一种预期的可能情况,但调用者也可能希望中止其所处的逻辑流,但对该情况的处理肯定不同于数据库中的实际错误


作为一个参考示例,您会注意到大多数数据库不会将在查询中查找失败视为错误。这只是“未找到”的结果。

谢谢您的输入。是的,我知道这些事情。但是,如果在整个应用程序中采用第二种方法,我将永远不会在自己的代码中编写try/catch语句,唯一的try/catch语句将在请求中间件中。这样,如果出现异常,那么应该中断代码的其余部分,因为我没有预料到它。