I'm trying to figure out how to link multiple asynchronous calls and return a result. I am currently trying to asynchronously user data first, and update user data asynchronously and return result, but it seems like it is not working :( i used map { result => Ok(result)}, but play still thinks that I am returning an object. any help?
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("")))
}
}
}
})
}
The main part that i am having issue is this part. I think it is matter of some syntax. Could someone help? Thanks
updateUserOnService(email, userData.f_name, userData.l_name, userData.new_password) map { result =>
Ok("please")
}
The issue is with your types and that they don't match up with the required ones.
.foldhas to result inFuture[Result]in both branches (the error and the success ones).In the successful form bind branch you have this:
Looking at your first operation we see:
One big issue here is that the
Nonecase is not handled! (but this is does not cause the types not matching up). Having something like the following will solve this:case None => Future.successful(BadRequest(...))So moving on: in the
Someyou have the following:This is where the issue is:
getUserwill return with aFuture[X]and when you map over it you will haveFuture[Y]whereYwill be whatuserCheck => ...evaluates to.In this case the types are totally mixed up, since when you do
if(usercheck)on the true branch you haveFuture[Result]on the false branch you haveResult. So the types don't align on both branches which is a big issue and the compiler will inferAnyfrom this.To fix this, in the false branch create a future:
Future.successful(BadRequest(....))Ok, now that we fixed the most inner type issues, let's start going backwards. Inside we have
Future[Result], if we go back one level (before thegetUser()) then we will haveFuture[Future[Result]]. Again this is not what we want, because we needFuture[Result].The solution to this is to
flatMapinstead ofmap, because withflatMapwhen you need to return with the same container type and it flattens it. A quick example to understand this:In the case of
Futures:So we see that we don't have double nesting, but just a single
Future.Going back to your example this would be my updated code that would work better: