我正在使用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")
}
每个参与者(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 语句连接来自每个参与者的列表,并生成一个长列表(resultData)。
我希望在一个参与者返回 None 的情况下,for 语句中的结果不会向串联添加任何内容,即 List()。
举个例子:
如果我得到: result1 = list(1, 2, 3), 结果2 = 无, result3 = 列表(4, 5),
我想要: 结果数据 = 列表(1, 2, 3, 4, 5)
在mapTo
这样之前,您可以将None
替换为Nil
:
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
。在演员receive
方法中,case l: List[Int]
你会遇到同样的问题。
您应该像这样为消息创建特殊类:
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]