I have come across functions that return Future
but also throw exceptions immediately. For example like this:
def func(): Future[String] {
if (something) {
// this
Future.failed(new RuntimeException("test"))
} else {
// and this
throw new RuntimeException("test")
}
}
This behaviour seems annoying for the caller, because you have to do something like this to catch both errors:
try {
func() recover {
case e: Exception => handleError(e)
}
} catch {
case e: Exception => Future.successful(handleError(e)) //or Future.failed etc
}
I have noticed that the WSClient
in play framework does this (both throwing exceptions if the URL is malformed, and returning a Future
which fails if the HTTP request fails).
Is this good practice? Is there a better way to handle errors from functions that behave like this?
Future
is used to return something eventually, but its not clear when this actually happens.
Coming from a .NET perspective (we have Task
): an exception should be thrown if the request is clearly invalid (such as an malformed url). You already know this before actually making the web request, so there is no need in delaying the exceptions.
On the other hand, if the server is down (timeout?) or the server returns something your client doesn't understand: this can and must be handled at a later time, since the response is not directly available when making the call. We would be able to block until the response is available, but that would render the Future
useless.
I think this is best compared with the 'Exit early' programming style.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With