Given the following List
of integers...
val l = List(1, 2, 3)
... I need to invoke 2 methods that return a Future
on each element and obtain the following result:
Future(Some(1), Some(2), Some(3))
Here below is my try:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
def f1(i: Int) = Future(i)
def f2(i: Int) = Future { if (i % 2 == 0) throw new Exception else i }
val l = List(1, 2, 3)
val results = Future.sequence(l.map { i =
val f = for {
r1 <- f1(i)
r2 <- f2(i) // this throws an exception if i is even
} yield Some(r1)
f.recoverWith {
case e => None
}
})
If f2
fails, I want to recover and continue with the remaining elements. The code above doesn't work since recoverWith
is never invoked, even if f2
fails.
How do I recover when f2
fails so that the final result is something like this?
Future(Some(1), None, Some(3))
The second element should be None
because f2
fails when the input integer is even (i.e. 2).
when recoverWith
has output type as Future
, it works fine.
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
def f1(i: Int) = Future(i)
def f2(i: Int) = Future { if (i % 2 == 0) throw new Exception else i }
val l = List(1, 2, 3)
val results = Future.sequence(l.map { i =>
val f = for {
r1 <- f1(i)
r2 <- f2(i) // this might throw an exception
} yield Some(r1)
f.recoverWith {
case e => Future { println("Called recover " + i); None } // wrapped in Future
}
})
results onComplete println
result:
// Called recover 2
// Success(List(Some(1), None, Some(3))
// tried with scala version: 2.10.4