处理 monad (Future) 包装另一个 monad (Option) 的数据结构的最佳方法是使用 Monad Transformer(我假设你对 monad 的一般概念很熟悉)。
例如,我们可以制作monad转换器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)
}
}
然后,我们可以像这样对内部 monad (Option) 进行操作:
val futureOption = OptionT(Future(Right("Yes")))
futureOption.fold(identity, "No") // Future[String]: Future("Yes")
如您所见,使用 monad 转换器 (Future[Option[A]] => Future[A]) 处理内部 monad 非常简单
但要回答您的问题,要从Future[Option[User]] 返回Option[User],您将不可避免地需要使用Await.result 之类的东西来阻止,当然这非常不鼓励。
在 Web 服务器上下文中的应用程序代码中,通过利用 monad 转换器,您永远不必从开始(收到请求)到结束(发送响应)离开上下文 Future > 像上面那样。
关于播放框架,可以使用Action.async方法直接传递Future[A]作为响应。