简体   繁体   English

计算期货清单并返回结果未来

[英]Calculate the list of the futures and and return the result future

I have a function which takes futures Future[A]* and I want it to return a Future[List[A]] . 我有一个函数,它需要期货Future[A]* ,我希望它返回Future[List[A]]

def singleFuture[T](futures: List[Future[A]]): Future[List[A]] = {
  val p = Promise[T]
  futures filter { _ onComplete { case x => p complete x /*????*/ } }
  p.future
} 

And I also want the result future of type Future[List[A]] becomes completed immediately after the list futures List[Future[A]] have been completed. 并且我还希望在列表期货List[Future[A]]完成之后立即完成Future[List[A]]类型的结果未来。

That code doesn't work. 该代码不起作用。 I figure I should use flatMap here because there should be 2 internal loops: one for the future and one for promise. 我想我应该在这里使用flatMap ,因为应该有2个内部循环:一个用于未来,一个用于promise。 But how? 但是怎么样?

I'd like not use for comprehension here because I'd like to understand the process at the deeper lever. 我想理解,因为我想了解的过程中,在更深一层意义上不能用在这里。

This is already implemented for you: 这已经为您实现:

def singleFuture[T](futures: List[Future[A]]): Future[List[A]] = Future.sequence(futures)

You can, of course, look at the implementation of sequence: 当然,您可以查看序列的实现:

def sequence[A, M[_] <: TraversableOnce[_]](in: M[Future[A]])(implicit cbf: CanBuildFrom[M[Future[A]], A, M[A]], executor: ExecutionContext): Future[M[A]] = {
  in.foldLeft(Promise.successful(cbf(in)).future) {
    (fr, fa) => for (r <- fr; a <- fa.asInstanceOf[Future[A]]) yield (r += a)
  } map (_.result())
}

This can be simplified if you only want to deal with lists, and not with anything that has foldLeft: 如果你只想处理列表,而不是任何有foldLeft的东西,这可以简化:

def sequence[A](in: List[Future[A]]): Future[List[A]] = {
  in.foldRight[Future[List[A]](Promise.successful(Nil) {
    (fa, fr) => for { r <- fr; a <- fa } yield (a :: r)
  }
}

You can use foldRight to achieve this: 您可以使用foldRight来实现此目的:

def singleFuture[A](futures: List[Future[A]]): Future[List[A]] = {

    val p = Promise[List[A]]()
    p.success(List.empty[A])

    val f = p.future // a future containing empty list.

    futures.foldRight(f) { 
       (fut, accum) =>  // foldRight means accumulator is on right.

        for {
           list <- accum;  // take List[A] out of Future[List[A]]
           a    <- fut     // take A out of Future[A]
        }
        yield (a :: list)   // A :: List[A]
    }
}

if any future in futures list fails, a <- fut will fail, resulting in accum being set to failed future. 如果期货清单中的任何未来失败,< - fut将失败,导致将被设置为未来失败。

If you want to avoid using for, you can either expand it to flatMap as follows: 如果要避免使用for,可以将其展开为flatMap,如下所示:

  accum.flatMap( list => fut.map(a => a :: list))

Or you can use, async-await (noting that it is still an experimental feature). 或者您可以使用async-await(注意它仍然是一个实验性功能)。

def singleFuture[T](futures: List[Future[T]]): Future[List[T]] = async {

  var localFutures = futures
  val result = ListBuffer[T]()
  while (localFutures != Nil) {
        result += await { localFutures.head } 
        localFutures = localFutures.tail
  }
  result.toList
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM