处理未来理解Scala
我有一个演员,他收到了一条消息,并经营两个期货。这些未来可以并行运行,所以我想我可以使用一个for-comprehension来运行这两个未来,并将它们的结果合并为对发送者的一个响应。我可以自己从每一项中得到结果,但我不知道当它们都完成时,如何将它们聚合起来处理未来理解Scala,scala,akka,future,Scala,Akka,Future,我有一个演员,他收到了一条消息,并经营两个期货。这些未来可以并行运行,所以我想我可以使用一个for-comprehension来运行这两个未来,并将它们的结果合并为对发送者的一个响应。我可以自己从每一项中得到结果,但我不知道当它们都完成时,如何将它们聚合起来 def receive = { case "pcbStatus" => { val currentSender = sender //first future val wsf = (self
def receive = {
case "pcbStatus" => {
val currentSender = sender
//first future
val wsf = (self ? "workhorseStats")(5 seconds)
val psf = Future.traverse(context.children)(x => {
(x ? "reportStatus")(5 seconds)
});
val combined = for {
r1 <- wsf
r2 <- psf
} yield (r1, r2)
combined.onComplete {
case Success(result:Any) => {
val response = new SomeCaseClass(r1,r2)
println("YAY: " + response)
currentSender ! response
}
case Failure(failure) => {
println("FAIL: " + failure)
}
}
}
}
def接收={
案例“pcbStatus”=>{
val currentSender=发送方
//第一未来
val wsf=(自身?“工作状态”)(5秒)
val psf=Future.transverse(context.children)(x=>{
(x?“报告状态”)(5秒)
});
val组合=用于{
r1{
println(“失败:+失败)
}
}
}
}
有一种简单的方法可以组合期货。例如(没有阿克卡):
这两个期货的完成顺序无关紧要。您可以尝试反转两个成功触发器,您将得到相同的结果
我在这里使用
Promise
只是为了构建一个运行的示例;这与未来的结合无关。我已经编写了一个小示例,说明我认为您正在尝试做的事情。首先,两个参与者类:
class ParentActor extends Actor{
import context._
import akka.pattern.pipe
implicit val timeout = Timeout(5 seconds)
override def preStart = {
context.actorOf(Props[ChildActor], "child-a")
context.actorOf(Props[ChildActor], "child-b")
}
def receive = {
case "foo" =>
val fut1 = (self ? "bar").mapTo[Int]
val fut2 = Future.traverse(context.children)(child => (child ? "baz").mapTo[Int])
val aggFut = for{
f1 <- fut1
f2 <- fut2
} yield SomeResult(f1, f2.toList)
aggFut pipeTo sender
case "bar" =>
sender ! 2
}
}
class ChildActor extends Actor{
def receive = {
case "baz" =>
sender ! 1
}
}
运行此命令时,它应该打印Success(SomeResult(2,List(1,1))
这里有几件事。首先,使用
mapTo
允许已知类型,而不必处理Any
。其次,pipeTo
在这里是一个很好的选择,可以避免关闭发送方,它还简化了一点代码。但是你已经得到了一个未来[(Int,Int)](或者你的wsf和psf是什么类型的),然后在onComplete中展开它,那么问题出在哪里呢?我想获取结果(r1和r2)并用它们创建一个响应。。。更新代码以反映您编写新SomeCaseClass(r1,r2)的位置,r1
和r2
都不在范围内。然而,你可以在案例成功((r1,r2))=>
上进行匹配,跳过那些讨厌的任何业务。@RandallSchulz,那会超时,还有其他想法吗?你是问自己但你的演员没有理由回应的“WorkhorsStats”
。很自然,等待暂停。很好的回答。对于那些在搜索中遇到这个问题的人,我也没有从(self?“workhorseStats”)返回结果,当然这会导致它超时。关于不必关闭发件人的建议也非常有用@cmbaxter,谢谢你的全面回应,这正是我拍摄的目的。
class ParentActor extends Actor{
import context._
import akka.pattern.pipe
implicit val timeout = Timeout(5 seconds)
override def preStart = {
context.actorOf(Props[ChildActor], "child-a")
context.actorOf(Props[ChildActor], "child-b")
}
def receive = {
case "foo" =>
val fut1 = (self ? "bar").mapTo[Int]
val fut2 = Future.traverse(context.children)(child => (child ? "baz").mapTo[Int])
val aggFut = for{
f1 <- fut1
f2 <- fut2
} yield SomeResult(f1, f2.toList)
aggFut pipeTo sender
case "bar" =>
sender ! 2
}
}
class ChildActor extends Actor{
def receive = {
case "baz" =>
sender ! 1
}
}
implicit val timeout = Timeout(5 seconds)
val system = ActorSystem("foo")
val actor = system.actorOf(Props[ParentActor])
val result = actor ? "foo"
import system._
result onComplete{
case tr => println(tr)
}