我使用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)
答案 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]