如何从 EssentialAction 中的 Future 中恢复错误

How to recover an error from a Future in an EssentialAction

this post 的例子开始,我想知道如何处理 recover:

def HasToken(action: String => EssentialAction): EssentialAction = EssentialAction { requestHeader =>
  val maybeToken = requestHeader.headers.get("session")

  val futureIteratee: Future[Iteratee[Array[Byte], SimpleResult]] = maybeToken map { token =>
    //This returns a future...
    Session.find(token).map {
      case Some(session) => action(session)(requestHeader)
      case None => Done[Array[Byte], Result](Unauthorized("Invalid token"))
    }.recover {
      Done[Array[Byte], Result](Unauthorized("400 Error finding Security Token\n"))
    }
  } getOrElse {
    Future.successful(Done[Array[Byte], Result](Unauthorized("401 No Security Token\n")))
  }

  Iteratee.flatten(futureIteratee)
}

上面的代码无法编译,我总是收到以下错误消息:

[error] /home/j3d/projects/test/app/Security.scala:80: type mismatch;
[error]  found   : scala.concurrent.Future[play.api.libs.iteratee.Iteratee[_4,play.api.mvc.Result] forSome { type _4 >: _3 <: Array[Byte]; type _3 <: Array[Byte] }]
[error]  required: scala.concurrent.Future[play.api.libs.iteratee.Iteratee[Array[Byte],play.api.mvc.Result]]
[error]         } recover {
[error]           ^
[error] one error found
[error] (compile:compile) Compilation failed

我是不是漏掉了什么?

奇怪的是,我认为问题可能在于该函数没有推断出您需要的正确类型。这在过去发生在我身上,结果类型取决于现有的通用类型,例如U >: T.

虽然在尝试了您的代码片段之后,我注意到您没有为 recover 调用使用部分函数,​​在我修复它之后它编译没有任何问题。

Session.find(token).map {
    case Some(session) => action(session)(requestHeader)
    case None => Done[Array[Byte], Result](Unauthorized("Invalid token"))
}.recover {
    case _ =>
        Done[Array[Byte], Result](Unauthorized("400 Error finding Security Token\n"))
}