给出以下List
个整数...
val l = List(1, 2, 3)
...我需要调用2个方法,在每个元素上返回Future
并获得以下结果:
Future(Some(1), Some(2), Some(3))
以下是我的尝试:
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
}
})
如果f2
失败,我想恢复并继续使用剩余的元素。上面的代码不起作用,因为即使recoverWith
失败,也永远不会调用f2
。
当f2
失败时如何恢复,以便最终结果是这样的?
Future(Some(1), None, Some(3))
第二个元素应该是None
,因为当输入整数是偶数(即2)时f2
失败。
答案 0 :(得分:5)
当recoverWith
的输出类型为Future
时,它可以正常工作。
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
结果:
// Called recover 2
// Success(List(Some(1), None, Some(3))
// tried with scala version: 2.10.4
答案 1 :(得分:3)
recoverWith
应返回Future
的某些内容,因此您的示例甚至无法编译。
您可以使用recover
代替
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.recover { case _ => None }
})
此外,在您的具体示例中,您甚至没有使用r2
,因此您只能
val results = Future.sequence(l.map { i =>
f1(i).map(Some(_)).recover { case _ => None }
})