Scala Future with Option()

时间:2014-12-02 08:50:02

标签: scala option future

我使用future创建三个actor任务,然后在完成后尝试收集所有三个。 当前代码如下:

implicit val timeout = Timeout(5.seconds)
  val result1 = actor1 ? DataForActor(data)
  val result2 = actor2 ? DataForActor(data)
  val result3 = actor3 ? DataForActor(data)
  val answer = for {
    a <- result1.mapTo[List[ResultData]]
    b <- result2.mapTo[List[ResultData]]
    c <- result3.mapTo[List[ResultData]]
  } yield (a ++ b ++ c).sorted
  answer onComplete {
    case Success(resultData) =>
      log.debug("All actors completed succesffully")
      successActor ! SuccessData(resultData.take(2))
    case Failure(resultData) =>
      log.info("actors failed")
  }

每个actor(actor1,actor2,actor3)操纵数据并返回None或Option(List(resultData)),如下面的代码所示:

val resultData = if(data.size == 0) None else {
  data.map {
    ...
    try {
      ... //manipulation on resultData
      Option(resultData)
    }
    catch {
      case e: Exception => None
    }
  }.flatten
}

for语句连接每个actor的列表,并生成一个长List(resultData)。

我希望在一个actor返回None的情况下,它在for语句中的结果不会向串联添加任何内容,即List()。

一个例子:

如果我得到:     result1 = List(1,2,3),     result2 =无,     result3 = List(4,5),

我想:     resultData = List(1,2,3,4,5)

1 个答案:

答案 0 :(得分:3)

您可以None之前用Nil替换mapTo

result1.map{
  case None => Nil
  case x => x
}.mapTo[List[ResultData]]

请注意,您应该避免mapTo使用类似List的通用类型:

Future("x" :: Nil).mapTo[List[Int]]
// res0: scala.concurrent.Future[List[Int]]

Future("x" :: Nil).mapTo[List[Int]] foreach { _.map( _ + 1 ) }
// java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer

由于类型删除mapTo无法证明您有Int的列表,而不是某些其他类型的List。在case l: List[Int] actor方法中,receive会遇到同样的问题。

你应该为你的消息创建一个特殊的类:

sealed trait ResultList { def data: List[ResultData] }
case class NotEmptyResult(data: List[ResultData]) extends ResultList 
case object EmptyResult extends ResultList { def data: List[ResultData] = Nil }

result1.mapTo[ResultList]