【问题标题】:Playframework: Type mismatch found scala.concurrent.Future[play.api.mvc.Result] required: play.api.mvc.ResultPlayframework:发现类型不匹配 scala.concurrent.Future[play.api.mvc.Result] 需要:play.api.mvc.Result
【发布时间】:2016-09-23 10:50:08
【问题描述】:

我在 PlayFramework 的控制器中有以下代码:

  def auth = Action.async(parse.json) { request =>
    {

      val authRequest = request.body.validate[AuthRequest]
      authRequest.fold(
        errors => Future(BadRequest),
        auth => {
          credentialsManager.checkEmailPassword(auth.email, auth.password).map {

            case Some(credential: Credentials) => {

              sessionManager.createSession(credential.authAccountId).map { //Throws an error
                case Some(authResponse: AuthResponse) => Ok(Json.toJson(authResponse))
                case None => InternalServerError

              }

            }

            case (None) => Unauthorized
          }

        })
    }
  }

我在上面的错误注释行中收到以下错误:

Type Mismatch:
[error]  found   : scala.concurrent.Future[play.api.mvc.Result]
[error]  required: play.api.mvc.Result
[error]               sessionManager.createSession(credential.authAccountId).map {

那里的 createSession 调用返回 Future[Option[Object]],但我不知道如何解决这个问题。

任何帮助将不胜感激。

【问题讨论】:

  • 您的credentialsManager.checkEmailPassword 方法返回什么?
  • 返回一个Future[Option[Credentials]],定义为def checkEmailPassword(email: String, password: String): Future[Option[Credentials]]
  • .map 更改为.flatMap,将credentialsManager.checkEmailPassword(auth.email, auth.password).mapcase (None) => Unauthorized 更改为case None => Future(Unauthorized)
  • 太棒了!那行得通。您能否也解释一下背后的原因?我会假设它会使外部Future[Option[Credentials]] 变平,但这对内部映射/返回类型有何影响?

标签: scala playframework-2.5


【解决方案1】:

简短回答: 将credentialsManager.checkEmailPassword(auth.email, auth.password).mapcase (None) => Unauthorized 中的.map 更改为.flatMap,并将case (None) => Unauthorized 更改为case None => Future(Unauthorized)

解释:

credentialsManager.checkEmailPassword(auth.email, auth.password) 返回一个Future[Option[Credentials]] 并且在其上的映射将始终返回一个Future 并且在其中sessionManager.createSession(credential.authAccountId) 也返回一个Future 所以,credentialsManager.checkEmailPassword(auth.email, auth.password) 的最终结果是Future[Future[something]] 以避免这种情况你可以改为flatten 它然后map 它,它可以通过flatmap 一步完成

【讨论】:

  • 值得注意的是,期货上的flatten 将在 Scala 2.12 github.com/viktorklang/blog/blob/master/… 中可用。现在你必须flatMap(identity)
  • 好吧,mapflatMapfilter 是 monads 本身可用的一些操作。
  • 感谢您的解释!
【解决方案2】:

不确定,但这应该可以:

def auth = Action.async(parse.json) { request =>
{

  val authRequest = request.body.validate[AuthRequest]
  authRequest.fold(
    errors => Future(BadRequest),
    auth => {
      credentialsManager.checkEmailPassword(auth.email, auth.password).flatMap { //flatMap

        case Some(credential: Credentials) => {

          sessionManager.createSession(credential.authAccountId).map {
            case Some(authResponse: AuthResponse) => Ok(Json.toJson(authResponse))
            case None => InternalServerError

          }

        }

        case None => Future(Unauthorized) //Wrap it
      }

    })
}

}

这是对您的代码的简化,带有一些 cmets。我希望这足以抓住这个想法:

 Future(Option("validCredentials")).flatMap {
   case Some(credential) => Future("OK")
   case None => Future("Unauthorized")
 }
 //Future[Option[String]].flatMap(Option[String] => Future[String])
 //Future[A].flatMap(A => Future[B]) //where A =:= Option[String] and B =:= String

【讨论】:

    【解决方案3】:

    Future("Unauthorized") 这无效请使用 Future.successful(Ok("OK")) Future.successful(BadRequest(Unauthorized))

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多