Is there a substantial difference between throwing vs returning an error from a service class?
class ProductService {
async getProduct(id) {
const product = await db.query(`...`)
if (!product) {
throw new ProductNotFoundError()
}
return product
}
// VS
async getProduct(id) {
const product = await db.query(`...`)
if (!product) {
return {
data: null,
error: new ProductNotFoundError()
}
}
return {
error: null,
data: product
}
}
}
In this example, I'd like to raise an error message if a product is not found ( supposedly returning null is not enough, maybe I need to also provide additional info why the product is not found ).
As a general design principle, is there a preferred approach, are there any substantial pros/cons of both approaches?
I've been doing the throw new Error
example, but then the code gets riddled with try/catch or .then/.catch statements, which make it somewhat harder to reason about.
What I don't particularly like about throwing errors is.. they are not unexpected. Obviously, I expect that a product might not be found, so I added a piece of logic to handle that part. Yet, it ends up being received by the caller the same way, for example, a TypeError is received. One is an expected domain error, the other one is unexpected exception.
In the first scenario, if I return an object with data
and error
properties ( or I can return an object with methods like isError
, isSuccess
and getData
from each service, which is similar ), I can at least trust my code to not raise exceptions. If one happens to arise, then it will be by definition unexpected and caught by the global error handlers ( express middleware, for example ).
question from:
https://stackoverflow.com/questions/65875386/throwing-vs-returning-errors-from-service-classes 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…