0

I am curious about how it is possible to return a future that contains a string value that is calculated in a separate thread and doesn't block the calling thread.

I have tried using a Runnable and passing it into a thread pool, but the overridden "run" method cannot return anything for the future, so that didn't work. I feel like I should be returning a future within my main future that gives back the string when it is done creating it, but I am not sure how. I want the outside future to immediately return.


def find(): Future[String] = {
    Future {
        val f = Future {
           getString() // This future gets the string and doesn't block the outside future from immediately returning

        }
        val s = Await.result(f, Duration.Inf)
        s
    }
}

How could I get the inner future to calculate a value without blocking the outer future from immediately returning? Thanks!

Max Vollmer
  • 8,412
  • 9
  • 28
  • 43
  • 2
    Why not just return in inner `Future`? What do you want the outer future to return? – Tim Apr 21 '19 at 15:14

1 Answers1

1

Your simplified code is a little confusing, but I'm guessing that what you really want to do is flatten a Future[Future[String]] to a Future[String]. If you can avoid creating the outer future in the first place (which your code would suggest) then you don't need to do this - just return a Future[String] without awaiting it, and you won't block a thread.

If you want to flatten the Future[Future[String]] then there are a few explanations here. In short, if you're in Scala 2.12+, you can just call f.flatten. Before that, use f.flatMap(identity) (where f is your Future[Future[String]]).

If you're writing Await.result anywhere except the outermost point in your code, you're probably doing it wrong: lookup how to use map and flatMap, and for comprehensions (which make chains of map and flatMap look a little neater).

gandaliter
  • 9,863
  • 1
  • 16
  • 23
  • What is the signature of the inner `find`? It looks from your code like it's the same method as the outer `find`, but if it were then it would just recurse forever, so I presume it's not. Can you elaborate a little on what you're trying to do, as I'm still confused. – gandaliter Apr 21 '19 at 15:17
  • `Future[String]` represents something that will eventually be a string, and might or might not already be one. The idea of it is that you can immediately return from your method, even though the actual result isn't available yet. Conceptually, you have a database call which might not return immediately. Do you want to add the resulting string to a queue as soon as it's available, or do you want to queue up `Future`s even though you won't know when they'll be ready? – gandaliter Apr 21 '19 at 15:33
  • Okay, so there's no need for an outer `Future` - just return the one you have, and add it to the queue. Nothing will block if you don't call `Await`, except perhaps the actual call to the database, but if it's returning a `Future` then it'll be fine. – gandaliter Apr 21 '19 at 15:39