David Portabella David Portabella - 2 months ago 20
Scala Question

on scala, how to wait for a Future.onFailure to complete?

Scala futures:
With Await.result I can wait for the future to complete before terminating the program.

How can I wait for a Future.onFailure to complete before terminating the program?

package test

import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future}
import scala.concurrent.ExecutionContext.Implicits.global

object Test5 extends App {
def step(i: Int): Future[String] = Future {
Thread.sleep(1000)
if (i == 3) throw new Exception("exception on t3")
Thread.sleep(1000); val s = s"done: $i"; println(s); s
}

val task: Future[String] = step(1).flatMap(_ => step(2).flatMap(_ => step(3)))

task.onFailure {
case e: Throwable => println("task.onFailure. START: " + e); Thread.sleep(3000); println("task.onFailure. END.")
}

try {
val result: String = Await.result(task, Duration.Inf)
println("RESULT: " + result)
} catch {
case e: Throwable => println("Await.result.try catch: " + e)
}

// without this, "task.onFailure. END." does not get printed.
// How can I replace this line with something such as Await.result([the task.onFailure I set previously])
Thread.sleep(5000)

println("END")
}


Note: Instead of using
task.onFailure
, I could catch the exception on
Await.result
(as in the example). But I would prefer to use
task.onFailure
.




Update
A solution is to use
transform
or
recover
as proposed by Ryan. In my case, I needed something more, and I've added this alternative answer: on scala, how to wait for a Future.onFailure to complete?

Answer

onFailure returns Unit. There's no way to block on that.

Either catch the exception on Await.result or use transform or recover to side-effect on the exception.