播放2.0 Scala和异步回调

时间:2012-09-25 14:33:10

标签: scala playframework-2.0

我想对我的数据库进行两次调用,这将需要一段时间才能返回结果,我不想阻止当前线程。我用Akka Futures来包装数据库调用。

我没有等待(阻塞)两个调用返回,而是指定要调用的回调函数,然后可以呈现响应。我怎么做?这是我的控制器代码:

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

1 个答案:

答案 0 :(得分: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块。 Async需要Promise,并返回AsyncResult,这是[{1}}的子类型(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 } 完成时调用map函数,因此保持非阻塞状态。整个块快速返回promise,然后播放!通过在完成后返回客户端(以及释放Play!同时执行其他操作)来以类似的方式管理它。