无法使用Future

时间:2016-12-30 22:05:51

标签: scala

StackOverflow上有一些关于如何处理Futures列表的建议,但我想尝试自己的方法。但我无法编译以下代码

我有一份期货清单。 我想算一下他们中有多少人通过或失败了。我应该得到(2,1) 我将它存储在一个元组中 我想要采用的方法是遍历列表中的每个元素。列表的元素是Future [Int]。对于每个元素,我调用flatMap调用下一个递归循环(我假设如果调用flatMap,那么特定的未来会成功,所以我增加传递计数)。类似地,我想在恢复和递增失败计数中调用递归的下一个循环,但我收到了编译错误。

import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success, Try}
import scala.concurrent.duration._
import scala.language.postfixOps

object ConcurrencyExample extends App {

  type pass = Int
  type fail = Int

  val time = System.currentTimeMillis()

//use recursion to process each Future in the list 
  def segregate(l:List[Future[Int]]):Future[Tuple2[pass,fail]] = {
    def go(l:List[Future[Int]],t:Tuple2[pass,fail]):Future[Tuple2[pass,fail]] = {
        l match {
          case Nil => Future{t}
            //l is List of Future[Int]. flatMap each successful Future 
            //recover each failed Future
          case l::ls => {
            l flatMap (x => go(ls, (t._1 + 1, t._2)))
              **l.recover({ case e => go(ls, (t._1 + 1, t._2))})**//I get error here
          }
        }
    }
    go(l,(0,0))
  }

//hardcoded future
  val futures2: List[Future[Int]] = List(Future {
    1
  }, Future {
    2
  }, Future {
    throw new Exception("error")
  })


  val result = segregate(futures2)
  result onComplete {
    case Success(v) => println("pp:" + v)
    case Failure(v) => println("fp:" + v)
  }

  Await.result(result,1000 millis)
}

2 个答案:

答案 0 :(得分:2)

@ evan058关于恢复的签名是正确的。但您可以通过将 recover 更改为 recoverWith 来修复您的程序。

recoverWith recover ,因为 flatMap map

这是完整的解决方案(具有轻微的风格改进):

import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success, Try}
import scala.concurrent.duration._
import scala.language.postfixOps

object ConcurrencyExample extends App {

  type pass = Int
  type fail = Int

  val time = System.currentTimeMillis()

  //use recursion to process each Future in the list
  def segregate[T](fs:List[Future[T]]):Future[(pass,fail)] = {
    def go(fs:List[Future[T]],r:Future[(pass,fail)]):Future[(pass,fail)] = fs match {
      case Nil => r
      case l::ls =>
        val fx = l.transform({_ => (1, 0)}, identity).recoverWith[(pass,fail)]({case _: Exception => Future(0, 1) })
        for (x <- fx; t <- r; g <- go(ls, Future(t._1+x._1,t._2+x._2))) yield g
    }
    go(fs,Future((0,0)))
  }

  //hardcoded future
  val futures2 = List(Future(1), Future(2), Future(throw new Exception("error")))    

  val result = segregate(futures2)
  result onComplete {
    case Success(v) => println(s"successes: ${v._1}, failures: ${v._2}")
    case Failure(v) => v.printStackTrace()
  }

  Await.result(result,1000 millis)
}

答案 1 :(得分:1)

如果您查看docs,则recover的签名为:

def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Future[U]

您在recover上呼叫l这是Future[Int],因此recover期待U >: Int

但是,您再次呼叫go,其返回类型Future[(pass, fail)]不是>: Int