What's the cleanest way to map
the Exception
of a failed Future
in scala?
Say I have:
import scala.concurrent._ import scala.concurrent.ExecutionContext.Implicits.global val f = Future { if(math.random < 0.5) 1 else throw new Exception("Oh no") }
If the Future succeeds with 1
, I'd like to keep that, however if it fails I would like to change the Exception
to a different Exception
.
The best I could come up with is transform, however that requires me to make a needless function for the success case:
val f2 = f.transform(s => s, cause => new Exception("Something went wrong", cause))
Is there any reason there is no mapFailure(PartialFunction[Throwable,Throwable])
?
In method whenComplete (), you have access to the result and exception of the current completable future as arguments: you can consume them and perform your desired action. However, you cannot transform the current result or exception to another result.
For example, given a failed future with exception “Oops” which normally returns a string, we can use handle () to handle the result and exception, by either recovering from exception or returning the normal result msg directly: This completable future cf1 will contain the following result:
A Future in Scala allows us to treat concurrency in a declarative way, hiding the complexity of asynchronous programming. We can map a Future, changing the value computed concurrently. But, what about a failed Future? Can we map something that fails into a new value? In this tutorial, we’ll explain exactly how to do just that.
Indeed, the workaround existed, and it was calling first the map method to deal with the happy path and then calling the recover method. The latter allows us to recover a Future that completed exceptionally, turning it into something different from an exception.
There is also:
f recover { case cause => throw new Exception("Something went wrong", cause) }
Since Scala 2.12 you can do:
f transform { case s @ Success(_) => s case Failure(cause) => Failure(new Exception("Something went wrong", cause)) }
or
f transform { _.transform(Success(_), cause => Failure(new Exception("Something went wrong", cause)))}
You could try recoverWith
as in:
f recoverWith{ case ex:Exception => Future.failed(new Exception("foo", ex)) }
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