Await a future, receive an either

schmmd picture schmmd · Jan 28, 2014 · Viewed 33.4k times · Source

I'd like to await a scala future that may have failed. If I use Await.result the exception will be thrown. Instead, if I have f: Future[String] I would like a method Await.resultOpt(f): Option[String] or Await.resultEither(f): Either[String].

I could get this by using scala.util.control.Exception.catching or I could f map (Right(_)) recover { case t: Throwable => Left(t) }, but there must be a more straightforward way.

Answer

Dylan picture Dylan · Jan 28, 2014

You could use Await.ready which simply blocks until the Future has either succeeded or failed, then returns a reference back to that Future.

From there, you would probably want to get the Future's value, which is an Option[Try[T]]. Due to the Await.ready call, it should be safe to assume that the value is a Some. Then it's just a matter of mapping between a Try[T] and an Either[Throwable, T].

The short version:

val f: Future[T] = ...

val result: Try[T] = Await.ready(f, Duration.Inf).value.get

val resultEither = result match {
  case Success(t) => Right(t)
  case Failure(e) => Left(e)
}