3

我想对我的数据库进行两次调用,这需要一段时间才能返回结果,而且我不想阻塞当前线程。我使用 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))
}
4

1 回答 1

6

你很近。你可以简单地调用map一个 promise 来处理它。在 Async 块内,它保持非阻塞。相关文档(参见“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接受 aPromise,并返回 aAsyncResult,它是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完成时被调用,因此它保持非阻塞。这整个块用AsyncResult, 和 Play!快速返回。以类似的方式管理它,当它完成时返回客户端(并释放 Play!同时做其他事情)。

于 2012-09-25T14:41:12.220 回答