Is there sequential Future.find?

后端 未结 3 1473
春和景丽
春和景丽 2021-01-14 08:07

I have some side-effectful function,

def f(): Future[Int] = {
  val n = Random.nextInt()
  println(s\"Generated $n\")
  Future(n)
}

and I

相关标签:
3条回答
  • 2021-01-14 08:43

    If I understand the question, then you will have to block the thread to proceed sequentially. You can use Await to accomplish that.

    scala> def f(): Future[Int] = {
     |   val n = Random.nextInt()
     |   println(s"Generated $n")
     |   Future(n)
     | }
    f: ()scala.concurrent.Future[Int]
    
    scala> def success(n: Int): Boolean = n % 2 == 0
    success: (n: Int)Boolean
    
    scala> val s = Stream.fill(10)(f)
    

    Using your way, I get

    scala> Future.find(s)(success) map println
    Generated 551866055
    Generated -561348666
    Generated -1103407834
    Generated -812310371
    Generated -1544170923
    Generated 2131361419
    Generated -236722325
    Generated -1473890302
    Generated -82395856
    Some(-561348666)
    res16: scala.concurrent.Future[Unit] = scala.concurrent.impl.Promise$DefaultPromise@15a2d71
    

    I should get answer as Some(-561348666), which you can get as

    scala> s.find(x => success(Await.result(x,1 seconds))).get onSuccess {case p=> println(p)}
    -561348666
    
    0 讨论(0)
  • 2021-01-14 09:00

    Instead of using Stream I suggest using another approach. Using The Future's filter and recoverWith recursively:

    def findFirst[A](futureGen: => Future[A], predicate: A => Boolean): Future[A] = {
      futureGen.filter(predicate).recoverWith { case _ => findFirst(futureGen, predicate) }
    }
    
    findFirst(f, success)
    

    This will call the Futures one after the other until 'success' will return true.

    0 讨论(0)
  • 2021-01-14 09:08

    First, let's make the futures we aren't interested in fail:

    val s1 = s.map(_.filter(success))
    

    Now you can combine two such futures and get the first successful value using fallbackTo. And just fold the stream, starting with a known-bad future:

    def firstSuccess[T](stream: Stream[Future[T]]): Future[T] = 
      if (stream.isEmpty)
        Future.failed(new NoSuchElementException)
      else
        stream.head.fallbackTo(firstSuccess(stream.tail))
    
    0 讨论(0)
自定义标题
段落格式
字体
字号
代码语言
提交回复
热议问题