scala如何等待几个期货

scala如何等待几个期货,scala,future,Scala,Future,我有seq 我想做自动迭代 import scala.concurrent.{Await, Future} import scala.concurrent.duration._ import scala.concurrent.ExecutionContext.Implicits.global def f(x:String) = Future { x } val functions = Seq( () => f("a"), () => f("b"), () =>

我有seq

我想做自动迭代

import scala.concurrent.{Await, Future}
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global

def f(x:String) = Future { x }

val functions = Seq(
  () => f("a"),
  () => f("b"),
  () => f(""),
  () => f("d"),
  () => f("e"))

functions.takeWhile( x => Await.result(x(), 5 seconds) != "")
这会给你

res0: Seq[() => scala.concurrent.Future[String]] = List(<function0>, <function0>)
res0:Seq[()=>scala.concurrent.Future[String]]=List(,)
我不确定是否还有其他方法,但据我所知,如果你想根据未来的结果做出决定,你需要等待

编辑: 这是一种递归方法。但在我看来,有迭代器的是好的

import scala.concurrent.{Await, Future}
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global

def f(x:String) = Future { x }

val functions = Seq(
  () => f("a"),
  () => f("b"),
  () => f(""),
  () => f("d"),
  () => f("e"))


check(functions, 0)
def check(list:Seq[() => Future[String]], pos:Int):String = {
  if(list.size <= pos) return ""

  val res = Await.result(list(pos)(), 5 seconds)
  if(condition(res)) {
    res
  }
  else check(list, pos+1)
}

def condition(c:String):Boolean = if(c == "d") true else false
导入scala.concurrent.{wait,Future}
导入scala.concurrent.duration_
导入scala.concurrent.ExecutionContext.Implicits.global
def(x:String)=未来{x}
val函数=Seq(
()=>f(“a”),
()=>f(“b”),
()=>f(“”),
()=>f(“d”),
()=>f(“e”))
检查(功能,0)
def检查(列表:Seq[()=>Future[String]],位置:Int):String={

如果(list.size您可以将
迭代器
flatMap
一起使用。下面是一个简化的示例:

import scala.concurrent.Await
import scala.concurrent.Future
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global

val functions: Seq[() => Future[Int]] = Seq(
  () => Future(1),
  () => Future(2),
  () => Future(3),
  () => Future(4),
  () => Future(5)
)

def checkResult(result: Int): Boolean = result > 3

functions.iterator.flatMap { func =>
  val result = Await.result(func(), 5.seconds)
  if (checkResult(result)) Some(result) else None
}.next()
此代码将返回4

更新:

如果您只关心正确的结果,而不关心是否执行了所有的期货,则可以使用
fallBackTo

import scala.util._

functions.tail.foldLeft[Future[Int]](functions.head().filter(checkResult)) {
    case (result, function) =>
      result.fallbackTo(function().filter(checkResult))
}.onComplete {
  case Success(result) => s"Got one: $result"
  case Failure(exception) => s"Damn! Got NO result due to: $exception"
}
这将为您提供一个
未来
,它将通过我的示例谓词
x>3
完成
成功(4)

更新2

由于我发现自己有一些额外的时间,我冒昧地将其他答案(特别是来自)中的一些评论和建议与贷款模式方法结合起来:

import scala.annotation.tailrec
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

val functions: Seq[() => Future[Int]] = Seq(
  () => Future(1),
  () => Future(2),
  () => Future(3),
  () => Future(4),
  () => Future(5)
)

def checkResult(result: Int): Boolean = result > 5

def withFirstValidResult[A, B](futureFuncs: Seq[() => Future[A]], predicate: A => Boolean, defaultValue: A)(op: (A) => B): Future[B] = {
  @tailrec
  @inline def find(remaining: Iterator[Future[A]]): Future[A] = {
    if (remaining.hasNext) {
      remaining.next().filter(predicate).recoverWith {
        case _ =>
        find(remaining)
      }
    } else {
      Future.successful {
        println(s"No valid result found, falling back to default: $defaultValue")
        defaultValue
      }
    }
  }


  find(futureFuncs.iterator.map(_())).map(op)
}
现在,您可以将此函数用于任何类型的未来,并提供一个应使用第一个有效结果或默认值执行的操作(尽管在没有有效结果的情况下,我更希望使用带有正确错误处理的
失败
):

作为额外提示,如果您想加速函数,可以让迭代器使用
futureFuncs.iterator.buffered
,一次惰性地计算两个函数。这样,在计算一个未来结果时,迭代器将自动启动下一个未来

def firstF[A](seq: Seq[() => Future[A]], predicate: A => Boolean): Future[A] =
  seq.head().filter(predicate).recoverWith {
    case _ => firstF[A](seq.tail, predicate)
  }
方法
firstF
将返回与指定条件匹配的第一个
Future
。如果输入的
Future
s不匹配,则生成的
Future
将是
失败的
。否则,只需返回一些默认值即可

firstF(seq, predicate).recover { case _ => default }

注1此处的代码演示了基本原则,不区分计划内或计划外异常


注意2这段代码不是尾部递归的。

不完全是关于主题的,但我强烈建议scalaz任务优先于futures。我发现futures有一些奇怪的行为,比如IO被推迟到执行结束。注意:OP删除了他/她的问题。有解决方案不用等待吗?谢谢!知道我为什么得到Future.filte吗r谓词不满足?[NoTouchElementException:Future.filter谓词不满足]]@Ben.om如果你的未来结果没有一个符合
checkResult
中的谓词,就会发生这种情况。人们通常会在
onComplete
onFailure
中处理这种情况。我将编辑我的答案作为一个例子。我喜欢你的解决方案w/
折叠
有没有解决方案可以等待?如果你依赖于它的话就不会了如果你想过滤并删除与你的条件不匹配的每个条目,那么是的。好的,但在这个解决方案中,当它完成时,我得到的是函数而不是值。我想这是另一种可行的方法。否则,使用迭代器。在这个解决方案中,我没有得到任何切理元例外:空头list@Ben.om如果没有任何元素与谓词匹配,则会出现此异常。但是您在问题中没有指定此场景。好的,如果任何函数不太匹配,则可能会出现此异常,因此在本例中,我需要返回defult值。这是您第一次提到“默认”值。请修改您的问题。
firstF(seq, predicate).recover { case _ => default }