Scala For-Understarehension:如果未来失败,如何恢复和继续

j3d*_*j3d 2 scala future for-comprehension

给出以下List整数......

val l = List(1, 2, 3)
Run Code Online (Sandbox Code Playgroud)

...我需要调用2个方法来返回Future每个元素并获得以下结果:

Future(Some(1), Some(2), Some(3))
Run Code Online (Sandbox Code Playgroud)

以下是我的尝试:

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
  }
})
Run Code Online (Sandbox Code Playgroud)

如果f2失败,我想恢复并继续使用剩余的元素.上面的代码不起作用,因为recoverWith永远不会调用,即使f2失败.

如何在f2失败时恢复,以便最终结果是这样的?

Future(Some(1), None, Some(3))
Run Code Online (Sandbox Code Playgroud)

第二个元素应该是None因为f2当输入整数是偶数(即2)时失败.

Shy*_*nki 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 
Run Code Online (Sandbox Code Playgroud)

结果:

// Called recover 2
// Success(List(Some(1), None, Some(3))       

// tried with scala version: 2.10.4
Run Code Online (Sandbox Code Playgroud)