j3d
j3d

Reputation: 9734

Scala: How to wait for a Future

In the following code snippet, method bookExists invokes method find to determine whether the book identified by the specified id exists:

class BookStore {

  def find(id: String): Future[Option[Book]] = {
    // read from db
    ...
  }

  def bookExists(id: String): Boolean = {
    find(id).map {
      case Some(_) => true
      case _ => false
    }.recover {
      case e => false
    }
  }
}

The problem is that the class above doesn't compile probably because I need to wait until the Future actually completes. I always get the following error message:

[error] /home/j3d/test/BookStore.scala:118: type mismatch;
[error]  found   : scala.concurrent.Future[Boolean]
[error]  required: Boolean
[error]         ).map {
[error]               ^

What's the correct way to handle this case?

Upvotes: 1

Views: 1523

Answers (2)

Gangstead
Gangstead

Reputation: 4182

Unless you are awaiting the result you are mapping this Future[Option[Book]] to another future of type Future[Boolean]. Without the await the computation will take place after the find Future completes (if at all). Change your return type:

  def bookExists(id: String): Future[Boolean] = {   
    find(id).map { _ match {  // '_' in the map is a Option[Book] extracted from the Future[Option[Book]] find returns
        case Some(_) => true  // '_' in the match is Book extracted from the Option[Book] in the match statement
        case _ => false
      }.recover {
        case e => false
      }
    }
  }

Upvotes: 2

Rex Kerr
Rex Kerr

Reputation: 167921

Normally you'd return Future[Boolean] and thus defer the requirement to have the answer for as long as possible.

But if it is important to block until the answer is available, then use scala.concurrent.Await (preferably wrapped in a Try to catch errors).

Upvotes: 4

Related Questions