考虑Play Framework控制器中的以下代码:
val firstFuture = function1(id)
val secondFuture = function2(id)
val resultFuture = for {
first <- firstFuture
second <- secondFuture(_.get)
result <- function3(first, second)
} yield Ok(s"Processed $id")
resultFuture.map(result => result).recover { case t => InternalServerError(s"Error organizing files: $t.getMessage")}
以下是有关这些功能的一些细节:
function1
返回Future[List]
function2
返回Future[Option[Person]]
function1
和function2
可以并行运行,但function3
需要两者的结果。鉴于此信息,我有一些问题:
NotFound
返回function2
,我想返回None
,但我无法弄清楚如何做到这一点。recover
调用是否会处理Exception
抛出的任何一步? 答案 0 :(得分:2)
也许使用collect
,然后你可以recover
NoSuchElementException
- 是的,将从任何一步恢复失败。 resultFuture
将使用映射的Result
成功,或者在抛出的第一个异常时失败。
val firstFuture = function1(id)
val secondFuture = function2(id)
val resultFuture = for {
first <- firstFuture
second <- secondFuture.collect(case Some(x) => x)
result <- function3(first, second)
} yield Ok(s"Processed $id")
resultFuture.map(result => result)
.recover { case java.util.NoSuchElementException => NotFound }
.recover { case t => InternalServerError(s"Error organizing files: $t.getMessage")}
答案 1 :(得分:1)
我会选择Scalaz OptionT。也许当你只有一个函数Future [Optipn [T]]它有点矫枉过正,但是当你开始添加更多功能时它会变得非常有用
import scala.concurrent.ExecutionContext.Implicits.global
import scalaz.OptionT
import scalaz.OptionT._
import scalaz.std.scalaFuture._
// Wrap 'some' result into OptionT
private def someOptionT[T](t: Future[T]): OptionT[Future, T] =
optionT[Future](t.map(Some.apply))
val firstFuture = function1(id)
val secondFuture = function2(id)
val action = for {
list <- someOptionT(firstFuture)
person <- optionT(secondFuture)
result = function3(list, person)
} yield result
action.run.map {
case None => NotFound
case Some(result) => Ok(s"Processed $id")
} recover {
case NonFatal(err) => InternalServerError(s"Error organizing files: ${err.getMessage}")
}