2012-12-07 37 views
2

因爲我第一次使用Play 2進行開發,我發現我在我的控制器中做了很多事情(其中一個更簡單的例子) :多個數據庫訪問與多個Akka.futures VS包裝數據庫訪問在單一的未來

val promUser = Akka.future(UserService.findByUsername(access.username)) 
    Async(
    promUser.map { 
     _.map{ 
     user => { 
      val promService = Akka.future(ServiceService loadOnlyWithUser (id,user.id.get)) 
      Async(
      promService.map { _.map { service => 
       Ok(toJson(service)) 
      }.getOrElse(BadRequest("not accessible"))} 
     ) 
     } 
     }.getOrElse { 
     BadRequest("unauthorised") 
     } 
    } 
) 

單身將來會更好嗎?例如:

val promService = Akka.future{ 
    val userOption = UserService.findByUsername(access.username) 
    userOption.map(user => { 
     ServiceService loadOnlyWithDeveloper (id,user.id.get) 
    }).getOrElse(None) 

    } 
    Async(
    promService.map { _.map { service => 
     Ok(toJson(service)) 
    }.getOrElse(BadRequest("unauthorised"))} 
) 

我想一方面是許多期貨/返回到控制器可能會增加開銷,就拱手組呼叫成一個未來將更具可讀性,但導致較大的「線程」運行在Akka系統中。對於更大的工作我有一個額外的Akka系統,所以這些只會包含最多4個SQL事務。至於我可以從Apache板凳工作,上面的例子之間沒有任何區別......有什麼我失蹤了?

回答

3

與您的示例在性能方面沒有任何區別,因爲它們是相同的。

當你寫:

val promUser = Akka.future(UserService.findByUsername(access.username)) 

沒有啓動,以評估Future,它只有在你那麼它映射執行。

據我所知,你需要考慮期貨構成。這是一個非常好的文檔,我會推薦:http://docs.scala-lang.org/sips/pending/futures-promises.html

要回答你的問題,那麼如果你有多個Futures,每個DB訪問一個,如果你需要執行一堆按順序查詢。例如。檢索記錄,然後刪除它。

如果您可以利用Futures(除了讓您的應用程序無阻塞),您可以利用for-comprehension語法,以便您可以同時運行兩個或更多個異步Futures。

for { 
    authUser <- User.findById(request.authUserId) 
    otherUser <- User.findById(id) 
} yield (authUser, otherUser) 

此外,我會建議使用flatMap譜寫自己的期貨一起,而不是多個Async{}塊。通過這種方式,您可以將多個期貨Future[Future[Result]]有效平整爲一個單一的未來,可以是AsyncResult

+0

謝謝,這是非常翔實的 – paullth

+0

沒問題!我只想快速地說我在for-comprehension示例中詳述的User.findById()函數返回Future(scala.concurrent.Future)。在Scala 2.10和Play 2.1中,您不需要編寫Akka.future,您可以直接在Scala中使用Future,因爲Future的所有第三方實現(包括Akka)都已移入Scala標準庫。 – alex