Map the Exception of a failed Future
25,132
Solution 1
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)))}
Solution 2
You could try recoverWith
as in:
f recoverWith{
case ex:Exception => Future.failed(new Exception("foo", ex))
}
Author by
theon
Updated on May 11, 2020Comments
-
theon almost 4 years
What's the cleanest way to
map
theException
of a failedFuture
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 theException
to a differentException
.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])
? -
Viktor Klang over 10 yearsFuture.failed is not evaluated on an ExeecutionContext: scala-lang.org/api/current/#scala.concurrent.Future$ see
failed
-
cmbaxter over 10 years@ViktorKlang, I must be confused then. I had made this assumption in looking at the
impl.KeptPromise
class'onComplete
method. In there, there are the two linesval preparedEC = executor.prepare; (new CallbackRunnable(preparedEC, func)).executeWithValue(completedAs)
. I assumed this to imply that even though we were giving an explicit value that it still for some reason was hitting the executor. It always seemed strange to me and I guess it's actually because I was misreading it. Thanks for the heads up. -
theon over 10 yearsThanks for the answers. My only hesitation with using
recover
/recoverWith
is that when I see it I immediately assume that the intention is to recover from a failure with a successful result. Maybe that is just me. Even so they are good alternatives, thanks! -
Jatin over 9 years@cmbaxter I still do not understand on how it doesn't hit ExecutionContext.
-
Kevin Meredith almost 9 years@cmbaxter - could you please check out my related question - stackoverflow.com/questions/31173982/….
-
MaatDeamon over 8 years@theon The fact that you use an exception or something else to signal to your program that something failed should not matter i think. Hence using recover or recoverwith should be the way to go i presume.
-
theon over 8 years@MattDeomon Since it is a failure, I'd rather use an Exception, so it triggers
onFailure
callbacks rather thanonSuccess
callbacks. I think it is more intuitive that way. I still also findtransform
more intuitive thanrecover
orrecoverWith
, because I am not recovering from a failure with a success, I am transforming a failure into another failure. That is true regardless of whether we use anException
or a regular class to signal the failure. -
owensmartin almost 7 yearsWhile this is a very clear syntax, we still have to
throw
the new exception, instead of getting to mapThrowable
toThrowable
. Is there a combinator for just that?