2015-10-04 59 views
1

鉴于整数以下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因为f2失败当输入整数为偶数(即2)。

回答

4

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 
2

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 } 
})