How to wait for several Futures?

前端 未结 8 871
故里飘歌
故里飘歌 2020-12-02 06:02

Suppose I have several futures and need to wait until either any of them fails or all of them succeed.

For example: Let there are 3 futures:

8条回答
  •  伪装坚强ぢ
    2020-12-02 06:15

    For this purpose I would use an Akka actor. Unlike the for-comprehension, it fails as soon as any of the futures fail, so it's a bit more efficient in that sense.

    class ResultCombiner(futs: Future[_]*) extends Actor {
    
      var origSender: ActorRef = null
      var futsRemaining: Set[Future[_]] = futs.toSet
    
      override def receive = {
        case () =>
          origSender = sender
          for(f <- futs)
            f.onComplete(result => self ! if(result.isSuccess) f else false)
        case false =>
          origSender ! SomethingFailed
        case f: Future[_] =>
          futsRemaining -= f
          if(futsRemaining.isEmpty) origSender ! EverythingSucceeded
      }
    
    }
    
    sealed trait Result
    case object SomethingFailed extends Result
    case object EverythingSucceeded extends Result
    

    Then, create the actor, send a message to it (so that it will know where to send its reply to) and wait for a reply.

    val actor = actorSystem.actorOf(Props(new ResultCombiner(f1, f2, f3)))
    try {
      val f4: Future[Result] = actor ? ()
      implicit val timeout = new Timeout(30 seconds) // or whatever
      Await.result(f4, timeout.duration).asInstanceOf[Result] match {
        case SomethingFailed => println("Oh noes!")
        case EverythingSucceeded => println("It all worked!")
      }
    } finally {
      // Avoid memory leaks: destroy the actor
      actor ! PoisonPill
    }
    

提交回复
热议问题