2012-09-25 82 views
3

我想兩次調用我的數據庫,這將需要一段時間來返回結果,我不想阻止當前線程。我用Akka Futures來包裝數據庫調用。玩2.0斯卡拉和異步回調

而不是等待(阻止)兩個調用返回,我想指定一個回調函數被調用,然後可以呈現響應。我怎麼做?這裏是我的控制器代碼:

def showPie = IsAuthenticated(Roles.validator) { user => implicit request => 
    val eventUid = request.session.get(EventUid).get 

    val printed = Akka.future(TicketRepository.getCountForState(eventUid, "Printed")) 
    val validated = Akka.future(TicketRepository.getCountForState(eventUid, "Validated")) 

    //this would be evil, because it would block: Ok(views.html.pie(printed.await(1000).get, validated.await(1000).get)) 

    //create a promise for all the promised results 
    val promise = Promise.sequence(List(printed, validated)) 

    //this doesnt work, but how can I make it work WITHOUT blocking this thread? 
    promise.callWhenResultIsReady(Ok(view.html.pie(promise.get)) 
} 

回答

6

你很近。您可以簡單地致電map承諾處理它。在異步塊內部,它保持非阻塞狀態。 Relevant documentation(請參閱「AsyncResult」)。

def showPie = IsAuthenticated(Roles.validator) { user => implicit request => 
    val eventUid = request.session.get(EventUid).get 

    val printed = Akka.future(TicketRepository.getCountForState(eventUid, "Printed")) 
    val validated = Akka.future(TicketRepository.getCountForState(eventUid, "Validated")) 

    //create a promise for all the promised results 
    val promise = Promise.sequence(List(printed, validated)) 
    Async { 
     promise map { res => 
      Ok("Got it!" + res) 
     } 
    } 
} 

編輯 從下面的評論,讓我們在異步塊一探究竟。 Async需要Promise,並返回AsyncResult,這是Result的子類型(這是Action需要的)。

Async { 
     // We take the promise, and add something akin to a callback 
     // function with `map`. This new function is called when `promise` 
     // is complete. 
     val result = promise map { res => // this is the redeemed promise 
      Ok("Got it!" + res) 
     } 
     result // this is the new promise 
    } 

從什麼時候開始promise結束的map函數被調用,這個保持無阻塞。整個區塊快速返回AsyncResult和Play!以類似的方式管理它,當它結束時返回客戶端(並釋放Play!在此期間做其他事情)。

+0

你知道它是如何工作的嗎?是否經常對Promise進行調查,以查看它是否準備好,如果不是,Akka會去做其他工作? –

+0

比這更好。由於你的調用將來會被執行,它們被添加到幕後的actor的消息隊列中,當它可用時(通常很快),它將處理它,然後調用任何完成函數。在Akka演員中,地圖,onComplete,onSuccess和onFailure以這種方式工作。你最後的承諾(序列)只是包裝其他人,並在每個部分完成時執行監聽功能。由於所有這些都發生在回調中,因此不需要輪詢。 –

+0

'map'調用返回另一個Promise,'Async'很樂意接受函數字面值的返回值。然後,它將偵聽器方法添加到* that *承諾將您的消息返回給客戶端。整個過程最終都是非阻塞的,並且不需要輪詢。 –