2015-06-11 80 views
2

我想弄清楚如何鏈接多個異步調用並返回結果。我目前正在嘗試異步用戶數據,並異步更新用戶數據並返回結果,但它似乎不工作:( 我使用map {result => Ok(result)},但仍認爲我是返回一個對象。任何幫助嗎?玩斯卡拉2.4鏈接異步調用

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(""))) 
      } 
     } 
     } 
    }) 
} 

主要部分,我有問題是這一部分。我認爲這是一些語法問題。有人能幫忙嗎? 感謝

updateUserOnService(email, userData.f_name, userData.l_name, userData.new_password) map { result => 
    Ok("please") 
} 
+1

你能分享的方法簽名(更具體的返回類型):'getUser'和'updateUserOnService'。沒有它,我們很難推斷出我們腦海中的類型:) –

+0

在我們的IDE中。 :-) –

+0

def updateUserOnService(email:String,firstName:String,lastName:String,n_password:String)= {0121} { 「email」 - > Seq(email),「firstName」 - > Seq(firstName),「lastName」 - > Seq(lastName),「n_password」 - > Seq(n_password))) –

回答

4

問題是與你的類型和他們不符合所需的

​​必須在兩個分支(錯誤和成功的分支)中產生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 
     } 
    }) 
} 
+0

嘿,非常感謝你!我無法上傳ote你的,因爲我沒有足夠的聲譽:(它現在工作!我知道類型是問題:( –

+0

@ShawnYoon如果你發現這回答了這個問題,那麼請將它標記爲綠色複選標記。 –