How to resolve a list of futures in Scala

后端 未结 3 1513
遇见更好的自我
遇见更好的自我 2021-02-02 11:05

I have a call that returns a Future. However, I need to make n calls so I will get back n futures. I am wondering how I would get the futures to all resolve before proceeding (w

相关标签:
3条回答
  • 2021-02-02 11:33

    I take it that you want to do something after the Futures are finished ,eg. a callback, without blocking the original call? Then you should do something like this:

    val futures = for (...) yield {
      future {
      ...
      }
    }
    
    val f = Future sequence futures.toList
    
    f onComplete {
      case Success(results) => for (result <- results) doSomething(result)
      case Failure(t) => println("An error has occured: " + t.getMessage)
    }
    

    http://docs.scala-lang.org/overviews/core/futures.html

    So you don't block with an await call, but you still wait for all Futures to complete and then do something on all results. The key aspects is using Future.sequence to join a lot of futures together and then to use a callback to act on the result.

    0 讨论(0)
  • 2021-02-02 11:43

    You can use Future.sequence(futureList) to convert a List[Future[X]] to a Future[List[X]]. And since the latter is just a simple Future, you can wait for it to finish with the help of the Await.ready or similar helpers.

    So you would have to keep a list of the futures you generate. Something like:

    val futures = new ListBuffer[Future[X]]
    while(counter < numCalls) {
        val future = call(counter)
        futures += future
        future.map { x =>
            //do stuff
        }
        counter += 1 
    }
    val f = Future.sequence(futures.toList)
    Await.ready(f, Duration.Inf)
    

    which you could also write as:

    val futures = (1 to numCalls).map(counter => {
        f = call(counter)
        f.map(x => ...)
        f
    })
    Await.ready(Future.sequence(futures), Duration.Inf)
    
    0 讨论(0)
  • 2021-02-02 11:53

    A little more functional:

    val futures = for {
      c <- 0 until 10
       } yield {
        val f = call(c) 
        f onSuccess {
          case x =>
          // Do your future stuff with x
        }
        f
      }
    Future.sequence(futures)
    
    0 讨论(0)
提交回复
热议问题