Playframework:发现类型不匹配scala.concurrent.Future[play.api.mvc.Result]必需:play.api.mvc.Result

Playframework:发现类型不匹配scala.concurrent.Future[play.api.mvc.Result]必需:play.api.mvc.Result,scala,playframework-2.5,Scala,Playframework 2.5,我在PlayFramework中的控制器中有以下代码: def auth = Action.async(parse.json) { request => { val authRequest = request.body.validate[AuthRequest] authRequest.fold( errors => Future(BadRequest), auth => { creden

我在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]]
,但我不知道如何解决这个问题


非常感谢您的帮助。

不确定,但这应该可以:

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
      }

    })
}
}

这是对代码的简化,并附有一些注释。我希望这足以抓住这个想法:

 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
简短答复: 将
凭证管理器中的
.map
更改为
.flatMap
。检查电子邮件密码(auth.email,auth.password)。将
案例(无)=>未经授权的
更改为
案例无=>未来(未经授权的)

说明:

credentialsManager.checkEmailPassword(auth.email,auth.password)
返回一个
Future[Option[Credentials]]
映射,该映射将始终返回一个
Future
并在其内部
sessionManager.createSession(credential.authcountId)
还返回一个
Future
So,
credentialmanager.checkEmailPassword(auth.email,auth.password)
的最终结果是
Future[Future[something]
为了避免这种情况,你可以将它展平,然后将它映射到
map
Future(“未经授权”)一步完成无效。请使用Future.successful(确定(“确定”))
Future.successful(BadRequest(Unauthorized))

您的
credentialsManager.checkEmailPassword
方法返回什么?它返回
Future[Option[Credentials]]
并定义为
def checkEmailPassword(电子邮件:字符串,密码:字符串):Future[Option[Credentials]]
.map
更改为
.flatMap
中的
credentialsManager。检查电子邮件密码(auth.email,auth.password)。将
案例(无)=>未经授权的
转换为
案例无=>未来(未经授权)
真棒!成功了。你能解释一下背后的原因吗?我假设它会将外部的
Future[选项[凭证]]
展平,但这会如何影响内部映射/返回类型?值得注意的是,Scala 2.12中将提供期货的
展平。现在您必须
flatMap(identity)
好了,
map
flatMap
filter
是monad本身可以使用的一些操作。谢谢您的解释!