Blankman
Blankman

Reputation: 267140

What are the various patterns that I could handle a Future[Option[user]]?

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

Answers (1)

Daniel Shin
Daniel Shin

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

Related Questions