我正在试图弄清楚如何链接多个异步调用并返回结果。我目前正在尝试异步用户数据,并异步更新用户数据并返回结果,但似乎它无法正常工作:( 我用map {result =>好的(结果)},但是游戏仍然认为我正在返回一个对象。有什么帮助吗?
Cache-Control: max-age=86400
我遇到问题的主要部分是这一部分。我认为这是一些语法问题。有人可以帮忙吗? 感谢
def updateUserData() = Action.async { implicit request =>
updateUserForm.bindFromRequest.fold(
errors => Future.successful(BadRequest(views.html.authenticated.settings.settings_hero(errors, Option(""), Option("")))),
{
case (userData) =>
request.session.get("email") match {
case Some(email) =>
getUser(email, userData.curent_password) map { userCheck =>
if (userCheck) {
updateUserOnService(email, userData.f_name, userData.l_name, userData.new_password) map { result =>
Ok("please")
}
//val e = updateUserOnService(email, userData.f_name, userData.l_name, userData.new_password) map {result => Ok("")}
// user is valid now update the user data
// call removeAuth to log out
// redirect to home
///Ok (updateUserOnService(email, userData.f_name, userData.l_name, userData.new_password) map { result => result})
//Redirect(routes.settings.index()).addingToSession("email" -> email)
} else {
BadRequest(views.html.authenticated.settings.settings_hero(updateUserForm.bindFromRequest.withGlobalError(Messages("error.login", email)), Option(""), Option("")))
}
}
}
})
}
答案 0 :(得分:4)
问题在于您的类型,并且它们与所需的类型不匹配。
.fold
必须在两个分支中产生Future[Result]
(错误和成功分支)。
在成功的表单绑定分支中,您有:
case (userData) => ... // The ... must evaluate to Future[Result]
看看你的第一个操作,我们看到:
request.session.get("email") match {
case Some(email) => ...
}
这里的一个重要问题是None
案件未得到处理! (但这不会导致类型不匹配)。如下所示将解决此问题:case None => Future.successful(BadRequest(...))
继续前进:在Some
中你有以下内容:
getUser(email, userData.curent_password) map { userCheck =>
if (userCheck) {
updateUserOnService(email, userData.f_name, userData.l_name, userData.new_password) map { result =>
Ok("please")
}
} else {
BadRequest(views.html.authenticated.settings.settings_hero(updateUserForm.bindFromRequest.withGlobalError(Messages("error.login", email)), Option(""), Option("")))
}
}
这就是问题所在:
getUser
将返回Future[X]
,当您映射时,您将Future[Y]
Y
将userCheck => ...
评估的内容。
在这种情况下,类型完全混淆,因为当您在真正的分支上if(usercheck)
时,您在假分支上有Future[Result]
Result
。因此类型不会在两个分支上对齐,这是一个很大的问题,编译器会从中推断Any
。
要解决此问题,请在假分支中创建未来:Future.successful(BadRequest(....))
好的,既然我们已经修复了最内在的类型问题,那么让我们开始倒退。如果我们返回一个级别(Future[Result]
之前),那么我们将getUser()
内部Future[Future[Result]]
。这不是我们想要的,因为我们需要Future[Result]
。
对此的解决方案是flatMap
而不是map
,因为当您需要使用相同的容器类型返回并使其展平时使用flatMap
。一个简单的例子来理解这一点:
Seq(1, 2, 3).flatMap(i => Seq(i, i))
// res0: Seq[Int] = List(1, 1, 2, 2, 3, 3)
如果是Future
s:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
Future(1).flatMap(i => Future(i*2))
// res1: scala.concurrent.Future[Int] = [....]
因此,我们发现我们没有双重嵌套,只有一个Future
。
回到你的例子,这将是我更新的代码,可以更好地工作:
def updateUserData() = Action.async { implicit request =>
updateUserForm.bindFromRequest.fold(
errors => Future.successful(BadRequest(views.html.authenticated.settings.settings_hero(errors, Option(""), Option("")))),
{
case (userData) =>
request.session.get("email") match {
case Some(email) =>
getUser(email, userData.curent_password).flatMap { userCheck =>
if (userCheck) {
updateUserOnService(email, userData.f_name, userData.l_name, userData.new_password) map { result =>
Ok("please")
}
} else {
Future.successful(BadRequest(views.html.authenticated.settings.settings_hero(updateUserForm.bindFromRequest.withGlobalError(Messages("error.login", email)), Option(""), Option(""))))
}
}
case None => Future.successful(BadRequest) // FIXME: Implement as you wish
}
})
}