I have a scenario in my code where I need to make a Future
fail based on a successful result that contains a certain value. I can make this work just fine via flatMap
, but I want to know if there is a cleaner way to make this work. First, a very simplified example:
import concurrent._
case class Result(successful:Boolean)
object FutureTest {
def main(args: Array[String]) {
import ExecutionContext.Implicits._
val f = Future{Result(false)}.flatMap{ result =>
result match{
case Result(false) => Promise.failed(new Exception("The call failed!!")).future
case _ => Promise.successful(result).future
}
}
f onFailure{
case x => println(x.getMessage())
}
}
}
So in my example here, I want the Future
to be failed if the Result
returned has a value of false
for its success indicator. As I mentioned, I can make this work okay with flatMap
, but the line of code I would like to eliminate is:
case _ => Promise.successful(result).future
This statement seems unnecessary. The behavior that I would like is to be able to define the condition and if it evaluates to true, allow me to return a different Future
as I am doing, but if it's not true, just leave things as they are (sort of like PartialFunction
semantics. Is there a way to do this that I'm just not seeing? I've looked at collect
and transform
and those don't seem to be the right fit either.
Edit
After getting the map
suggestion from @Rex Kerr and @senia, I created a PimpedFuture
and an implicit conversion to pretty up the code a bit like so:
class PimpedFuture[T](f:Future[T])(implicit ex:ExecutionContext){
def failWhen(pf:PartialFunction[T,Throwable]):Future[T] = {
f map{
case x if (pf.isDefinedAt(x)) => throw pf(x)
case x => x
}
}
}
The implicit
implicit def futToPimpedFut[T](fut:Future[T])(implicit ec:ExecutionContext):PimpedFuture[T] = new PimpedFuture(fut)
And the new handling code:
val f = Future{ Result(false) } failWhen {
case Result(false) => new Exception("The call failed!!")
}
I think this is a little cleaner while still utilizing the suggestion to use map
.
filter
method. – Azimuthfilter
. The issue there is that if my predicate is not true then the resultingFuture
is failed with aNoSuchElementException
and that is undesired. – Mis