播放Scala 2.4链接异步调用
我试图找出如何链接多个异步调用并返回结果。我目前正在尝试先异步更新用户数据,然后异步更新用户数据并返回结果,但它似乎不起作用:( 我使用了map{result=>Ok(result)},但play仍然认为我返回了一个对象。有什么帮助吗播放Scala 2.4链接异步调用,scala,asynchronous,playframework,playframework-2.0,Scala,Asynchronous,Playframework,Playframework 2.0,我试图找出如何链接多个异步调用并返回结果。我目前正在尝试先异步更新用户数据,然后异步更新用户数据并返回结果,但它似乎不起作用:( 我使用了map{result=>Ok(result)},但play仍然认为我返回了一个对象。有什么帮助吗 def updateUserData() = Action.async { implicit request => updateUserForm.bindFromRequest.fold( errors => Future.successful(Bad
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("")))
}
}
}
})
}
我遇到的主要问题是这一部分。我想这是一些语法问题。有人能帮忙吗?
谢谢
问题在于您的类型,它们与所需的类型不匹配
.fold
必须在两个分支(错误分支和成功分支)中产生未来[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
要解决此问题,请在false分支中创建一个future: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)
在未来的情况下
s:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
Future(1).flatMap(i => Future(i*2))
// res1: scala.concurrent.Future[Int] = [....]
所以我们看到我们没有双重嵌套,只有一个未来的
回到您的示例,这将是我更新的代码,可以更好地工作:
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
}
})
}
你能分享方法签名(更具体地说是返回类型)吗:getUser
和updateUserOnService
。没有它,我们很难在脑海中推断出类型:)def updateUserOnService(email:String,firstName:String,lastName:String,n_密码:String)={WS.url(“).post(Map(“email”->Seq(email),“firstName”->Seq(firstName),“lastName”->Seq(lastName),“n_password”->Seq(n_password)))def getUser(email:String,password:String)={WS.url(“).post(Map”(“email”->Seq(email),“password”->Seq(password))).Map(response=>response.body.contains(“true”)}对不起,我是个新手,因此,我不知道如何编辑或重新格式化代码,以便让你们更容易看到:(嘿,非常感谢!我无法提高你们的投票率,因为我没有足够的声誉:(它现在起作用了!我知道类型是问题所在:(@ShawnYoon)如果您发现这回答了问题,请使用绿色复选标记将其标记为已回答。
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
}
})
}