【问题标题】:Play 2.0 Scala and async callbacks播放 2.0 Scala 和异步回调
【发布时间】:2012-09-26 04:29:50
【问题描述】:

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

【问题讨论】:

    标签: scala playframework-2.0


    【解决方案1】:

    你已经接近了。您可以简单地致电map 承诺处理它。在 Async 块内,它保持非阻塞。 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,它是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! 来做其他事情)。

    【讨论】:

    • 你知道它是如何工作的吗? Promise 是否经常轮询以查看它是否准备就绪,如果没有,Akka 会去做其他一些工作吗?
    • 比这更好。由于您的调用是在未来执行的,它们被添加到幕后参与者的消息队列中,当它可用时(通常非常快),它将处理它,然后调用任何完成函数。在 Akka Actor 上,map、onComplete、onSuccess 和 onFailure 以这种方式工作。您的最后一个承诺(序列)只是包装其他承诺,并在每个部分完成时执行监听功能。由于所有这些都发生在回调中,因此不需要轮询。
    • map 调用返回另一个 Promise,Async 乐于接受它作为函数字面量返回值。然后,它向 that 承诺添加一个侦听器方法,以将您的消息返回给客户端。整个过程最终是非阻塞的,不需要轮询。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-03
    相关资源
    最近更新 更多