积累未来的最佳方式

时间:2015-02-25 10:30:58

标签: scala akka

假设我有一个返回Future的函数,根据此函数的结果,我可能需要再次调用它,否则我可能会立即返回。我需要在列表中累积这些结果。我想定义一个函数,将该列表作为Future返回。我有以下内容:

def foo: Future[Int] { ... }

def accum(i: Future[Int], l: List[Int]): Future[List[Int]] = i.map { i =>
    if (i >= max)
        l
    else 
        accum(foo, i :: l)
}

def test: Future[List[Int]] = accum(foo, List())

但是当然这不会编译,因为在map中调用accum()需要返回List [Int]而不是Future [List [Int]]。这样做的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

始终从内部块返回Future,然后使用flatMap

def accum(i: Future[Int], l: List[Int]): Future[List[Int]] =
  i.flatMap { i =>
    if (i >= max)
      Future.successful(l)
    else 
      accum(foo, i :: l)
  }

根据foo的来源,您可能还需要考虑,例如scalaz的foldLeftM而不是显式的递归函数。

答案 1 :(得分:0)

我认为以下内容适合您,

def foo: Future[Int] = ???

def accumulate( max: Int, f: () => Future[ Int ], list: List[ Int ] = List[ Int ]() ): Future[ List[ Int ] ] = {
  val intFuture = f()

  intFuture.flatMap( ( i: Int ) => {
    // if future is successfull
    if ( i < max ) {
      // If value less than max, keep on accumulating more 
      accumulate( max, f, list :+ i )
    }
    else {
      // If value not less than max, stop accumulating more
      // Just wrap the list in future and return
      val promiseOfList = Promise[ List[ Int ] ]()
      promiseOfList.complete( Success( list ) )
      promiseOfList.future
    }
  } ).fallbackTo( {
    // If this computation fails.... stop accumulating
    // Just wrap the list in future and return
    val promiseOfList = Promise[ List[ Int ] ]()
    promiseOfList.complete( Success( list ) )
    promiseOfList.future
  } )

}

val myListFuture = accumulate( max, foo )