Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Map the Exception of a failed Future

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])?

like image 802
theon Avatar asked Aug 15 '13 10:08

theon


People also ask

How to use the result and exception of a completable future?

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.

How to handle a failed future with exception “Oops”?

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:

Can we map a failed future in Scala?

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.

Is there a way to recover a future that completed exceptionally?

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.


2 Answers

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)))} 
like image 106
Viktor Klang Avatar answered Oct 22 '22 05:10

Viktor Klang


You could try recoverWith as in:

f recoverWith{   case ex:Exception => Future.failed(new Exception("foo", ex)) } 
like image 30
cmbaxter Avatar answered Oct 22 '22 05:10

cmbaxter