Cristian Boariu
Cristian Boariu

Reputation: 9621

Given a Future[T] can I write function with onComplete callback which returns T?

I have this method:

def findById(id: String): Customer = {
     (new CustomerDaoEs).retrieve(Id[Customer](id)) onComplete {
      case Success(customer) => customer
      case Failure(t) => {
        throw new InvalidIdException(id.toString, "customer")
      }
    }
  }

Of course, the issue is that this returns Unit instead of Customer... So basically onComplete does not really behave like pattern matching.

Is there any way to keep returning Customer (or Option[Customer]) and make this work nice (I mean to keep this onComplete clean structure)?

Upvotes: 3

Views: 615

Answers (2)

senia
senia

Reputation: 38045

You could change exception using recover method:

def findById(id: String): Future[Customer] = {
  (new CustomerDaoEs).retrieve(Id[Customer](id)).recover{ case _ => throw new InvalidIdException(id.toString, "customer") }
}

Then you could use your method like this:

val customer = Await.result(findById("cust_id"), 5.seconds)

Alternatively you could replace exception with None:

def findById(id: String): Future[Option[Customer]] = {
  (new CustomerDaoEs).
    retrieve(Id[Customer](id)).
    map{ Some(_) }.
    recover{ case _ => None }
}

Upvotes: 5

Joa Ebert
Joa Ebert

Reputation: 6715

The main issue is that onComplete is non-blocking. So instead you would have to use Await and return the result.

def findById(id: String): Customer = 
  Await.result(
    awaitable = (new CustomerDaoEs).retrieve(Id[Customer](id))),
    atMost = 10.seconds
  )

However I would rather suggest to keep the code non-blocking and make findById return Future[Customer].

Upvotes: 4

Related Questions