在以下操作中,它应该在命中URL后立即返回响应,而是等待直到所有Future块都启动,然后才发送响应。等到"开始第10组"即使"从行动中返回"也会在控制台中登录在点击URL后立即记录。
def test = Action { implicit request =>
Future.successful(0 to 150).foreach { items =>
items.grouped(15).zipWithIndex.foreach{ itemGroupWithIndex =>
val (itemGroup, index) = itemGroupWithIndex
Future {
logger.info("************** Starting for group " + index)
itemGroup.foreach { item =>
Thread.sleep(1000)
logger.info("Completed for item " + item)
}
}
}
}
logger.info("************** Returning from action **************")
Ok(views.html.test("test page"))
}
我无法理解这种延迟背后的原因,我怎样才能使此行动立即发送响应。
播放框架版本2.5.9
答案 0 :(得分:0)
您的操作不是异步。您有一个同步端点,这就是您在控制台上看到立即打印的返回操作的原因。您应该使用Action.async作为处理类型。使用异步操作可以极大地提高应用程序的整体性能,强烈建议在构建高吞吐量和响应式Web应用程序时使用。
答案 1 :(得分:0)
代码中的两点需要更改
异步操作:由于您使用的是Future,因此操作应该是异步的:Action.async{...}
。
无阻塞代码:使用Future和异步编程的全部意义不是要有一个代码来阻止"阻塞"执行。所以我建议删除代码的Thread.sleep(1000)
部分。
请注意,如果您以非阻塞的方式编写代码;每当action方法得到结果;它将执行所需的操作,例如记录或提供视图。
答案 2 :(得分:-1)
这是因为您的期货存在竞争条件。
您需要确保返回单个Future[T]
而不是Future[Future[T]]
(或任何分层差异)。
如果期货彼此独立,请使用Future.sequence
示例:
def future: Future[String] = Future.successful("hi")
def action = Action.async { _ =>
val futures: Seq[Future[String]] = (1 to 50).map(_ => future()).toSeq
val oneFuture = Future.sequence(futures)
oneFuture
}
这将避免竞争条件
仅供参考,这与Play框架无关。这是scala中的并发编程。