Reputation: 267140
I have a method that returns a Future[Option[User]]
def insertUser(...): Future[Option[User]] = { ... }
In my controller I am currently doing this:
val futureUser = userService.insertUser(...)
What are the various patterns in Scala can I handle this future to return the Option[User] eventually?
Upvotes: 0
Views: 70
Reputation: 5206
The best way to deal with a data structure where monad (Future
) wrapping another monad (Option
) is to use Monad Transformer (I'll assume that you are familiar with concepts of monad in general).
For example, we can make monad transformer OptionT
:
final case class OptionT[F[_], A](run: F[Option[A]]) {
def fold[X](some: A => X, none: => X)(implicit F: Functor[F]): F[X] =
F.map(run) {
case None => none
case Some(a) => some(a)
}
}
Then, we can operate on inner monad (Option
) like this:
val futureOption = OptionT(Future(Right("Yes")))
futureOption.fold(identity, "No") // Future[String]: Future("Yes")
As you can see, working on inner monad is straight-forward with monad transformer (Future[Option[A]] => Future[A]
)
To answer your question though, to return Option[User]
from Future[Option[User]]
, you will inevitably need to block with something like Await.result
and of course is hugely discouraged.
Within your application code in the context of web server, you'll never have to leave the context Future
from the start (request received) to the end (response sent) by leveraging monad transformers like the above.
With regards to play framework, you can use Action.async
method to pass Future[A]
directly as response.
Upvotes: 4