2012-09-25 84 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 *承诺将您的消息返回给客户端。整个过程最终都是非阻塞的,并且不需要轮询。 –