如何在Play框架2中等待控制器动作



我尝试编写动作来生成图片的拇指并显示给用户,如果它还没有生成。问题是:生成部分以异步方式运行,显示部分代码在生成部分完成之前运行。我是Scala和Play框架的新手,不能让show部分等待。我试过这样做:

def thumbs(profiletype: String, id: Int, filename: String, extention: String) = Action {
val content = File.getBinaryContent(pathToDir + filename + "." + extention)
content match {
  case Some(c) => Ok(c).as(File.getContentType(extention))
  case _ => val picture = Picture.getById(id)
      picture match {
        case None => NotFound("Page not found")
        case Some(p) => val rslt = Future (p.generateThumbs(pathToDir, profiletype))
          val r=rslt.map(a=>a)
          Await.ready(r, Duration(8, "second"))
            Logger.debug(pathToDir + filename + "." + extention)
            val content = File.getBinaryContent(pathToDir + filename + "." + extention)
            renderBinary(content, File.getContentType(extention))}
          }
}

像这样没有运气

def thumbs(profiletype: String, id: Int, filename: String, extention: String) = Action {
val content = File.getBinaryContent(pathToDir + filename + "." + extention)
content match {
  case Some(c) => Ok(c).as(File.getContentType(extention))
  case _ => val picture = Picture.getById(id)
      picture match {
        case None => NotFound("Page not found")
        case Some(p) => val rslt = Future (p.generateThumbs(pathToDir, profiletype))
          Await.ready(rslt, Duration(8, "second"))
            Logger.debug(pathToDir + filename + "." + extention)
            val content = File.getBinaryContent(pathToDir + filename + "." + extention)
            renderBinary(content, File.getContentType(extention))}
          }
}

这个Await不工作,Logger在p. generateththumb完成之前记录日志

与其异步生成缩略图并在等待缩略图生成时阻塞(使用Await.readyAwait.result),不如返回Future[Result]

在您的例子中,它看起来像(未经测试):
(我还将您的Option模式匹配转换为mapgetOrElse函数。)

def thumbs(
  profiletype: String, id: Int, filename: String, extention: String
) = Action.async { // return an (explicit) asynchronous result
  val filepath = pathToDir + filename + "." + extention
  File.getBinaryContent(filepath)
    .map ( content => 
       // we found the thumbnail, return its content as a Future[Result]
       Future.successful(Ok(content).as(File.getContentType(extention)))
    )
    .getOrElse {
      // we have not found the thumbnail, check if the Picture exists
      Picture.getById(id)
        .map { picture =>
          // we found the Picture, lets generate the thumbnails
          Future(picture.generateThumbs(pathToDir, profiletype))
            .map { futureResult =>
              // the thumbnails are created
              // return the content of the thumbnail 
              // and since we are in a Future.map this will be a Future[Result]
              Logger.debug(filepath)
              val content = File.getBinaryContent(filepath)
              renderBinary(content, File.getContentType(extention))
            }
        }
        // we could not find the Picture return a NotFound as Future[Result]
        .getOrElse(Future.successful(NotFound("Page not found")))
    }
}

这样我们只有一个阻塞线程来创建缩略图,而不是两个,一个创建缩略图,另一个等待直到第一个线程完成创建缩略图。

Play可以在创建缩略图时为其他请求服务,在创建缩略图后Play将响应缩略图。

最新更新