2016-02-29 88 views
1

考慮用於羣集的主/從選擇模型。斯卡拉來自多個未來呼叫的聚合結果

Member{ id: Long, isMaster: Boolean } 

我有以下方法道/回購:

MemberDao.findById(id:Long):Future[Option[Member]] 
MemberDao.update(id:Long, member: Member):Future[Unit] 
MemberDao.all() : Future[List[Member]] 

內MemberService,我試圖寫一個函數來isMaster設置爲false所有現有的成員,我這種瘋狂臃腫的代碼結束了:

class MemberService ... { 
    def demoteAllMembers() : Future[Boolean] = { 
    val futures = memberDao.all.map{ memberFuture => 
     memberFuture.map{ member => 
     memberDao.findById(member.id).map { existingMemberFuture => 
      existingMemberFuture.map { existingMember => 
      memberDao.update(existingMember.id, existingMember.copy(isMaster = false) 
      } 
     } 
     } 
     val results = Await.result(futures, 10 seconds) 

     // return something here 
    } 
    } 


} 

我的問題是:1。 應該如何return語句寫入處理成功/錯誤?例如成功時,返回Future(true)和失敗,返回Future(false) 2.這種重複映射未來的方式是在scala中進行異步編程的正確方法嗎?我知道這可能在Actor範例中寫得不同,可能好得多,但在OOP的情況下,這是最好的Scala能做到的嗎?

謝謝。

回答

2

爲什麼你在做MemberDao.findById的時候你已經手持一個會員? (你也將會員作爲會員處理,而它應該是一個Option [會員])。 此外,更新不需要將id作爲單獨的參數(在member中有一個可用)。 你不需要Await你的結果,因爲你的函數返回Future,你不需要返回Boolean:只是拋出一個異常信號失敗。 考慮這樣的事情:

def demoteAllMembers: Future[Unit] = memberDao.all.flatMap { 
    Future.sequence(_.foreach { 
    memberDao.update(_.copy(isMaster = false)) 
    }) 
}.map (_ =>()) 

並非所有臃腫,是嗎? :)

+0

有很大的意義,顯然是新手scala開發者在這裏,還有一個問題,memberDao.update需要一個成員,而不是Future [Member],這就是memberDao.all會返回的。所以我猜我需要做memberFuture =>映射嗎? – BZapper

+0

不,您的定義中'.all'會返回一個'Future [List [Member]]'。我的片段中的第一個'.flatMap'看起來在'Future'裏面,然後'foreach'遍歷'Member'列表。請注意,我已經更新瞭解決返回類型不兼容問題的答案:您需要在'.flatMap'內部有一個'Future.sequence'來將期貨列表轉換爲未來列表,然後在最後的丟棄列表中將'.map'轉換爲未來列表使得結果'Future [Unit]'而不是'Future [List [Unit]]'的列表 – Dima