Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
处理未来理解Scala_Scala_Akka_Future - Fatal编程技术网

处理未来理解Scala

处理未来理解Scala,scala,akka,future,Scala,Akka,Future,我有一个演员,他收到了一条消息,并经营两个期货。这些未来可以并行运行,所以我想我可以使用一个for-comprehension来运行这两个未来,并将它们的结果合并为对发送者的一个响应。我可以自己从每一项中得到结果,但我不知道当它们都完成时,如何将它们聚合起来 def receive = { case "pcbStatus" => { val currentSender = sender //first future val wsf = (self

我有一个演员,他收到了一条消息,并经营两个期货。这些未来可以并行运行,所以我想我可以使用一个for-comprehension来运行这两个未来,并将它们的结果合并为对发送者的一个响应。我可以自己从每一项中得到结果,但我不知道当它们都完成时,如何将它们聚合起来

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)
}