Failing a Future based on a successful result
You can do this with less effort with map
:
val f = Future{ Result(false) } map {
case Result(false) => throw new Exception("The call failed!!")
case x => x
}
but you still need to explicitly mention that you're passing the identity through.
Note that that you should not use andThen
in such cases. andThen
is for side effects, not for changing the result (unlike the Function1
method of the same name).
cmbaxter
Long time Java programmer who converted to Scala a few years back. I like building high performance systems built on top of Akka using other libraries like Unfiltered, Slick, Dispatch and Netty. If you like my Akka answers on Stackoverflow then you'll love my book, Mastering Akka. Pick yourself up a copy on pre-sale today. Links below: https://www.packtpub.com/application-development/mastering-akka https://www.amazon.com/Mastering-Akka-Christian-Baxter-ebook/dp/B01GOJCXPU/ref=sr_1_1?ie=UTF8&qid=1465469018&sr=8-1&keywords=Mastering+Akka Linked In http://www.linkedin.com/pub/chris-baxter/3/429/5ab/
Updated on July 10, 2022Comments
-
cmbaxter almost 2 years
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 viaflatMap
, 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 theResult
returned has a value offalse
for its success indicator. As I mentioned, I can make this work okay withflatMap
, 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 likePartialFunction
semantics. Is there a way to do this that I'm just not seeing? I've looked atcollect
andtransform
and those don't seem to be the right fit either.Edit
After getting the
map
suggestion from @Rex Kerr and @senia, I created aPimpedFuture
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
.