在单个 Play 操作中进行独立的 Slick 查询

Making independent Slick queries inside of single Play action

我有异步播放 Action,它使用 Slick 从数据库中检索数据。显然,Slick 使用 Futures 来避免阻塞:

def show(id: Long) = Action.async {
 db.run(entities.filter(_.id === id).result.headOption).map {
   case None => templateFor("NEW_OBJECT")
   case Some(x) => Ok(x)
 }
def templateFor(code: String): Future[Result] = {
  db.run(templates.filter(_.code === code).result.headOption).map {
    case None => InternalServerError("No template")
    case Some(x) => Ok(x)
  }
}

问题是调用了templateFor()returnsFuture,所以整个ActionreturnsFuture[Future[Result]]这不是Play 所期望的。所以,我想摆脱那个嵌套的 Future。完成它的简单方法是 Await 完成,但我想避免不必要的阻塞。如果我能够将 templateFor() 函数生成的 Future[Result] 和 return 原封不动地从我的 Action 中获取,那就太好了,从而将外部 Future 替换为它。

你可以使用 flatMap

对于任何 monandic 结构,例如 Future[T]flatMap 接受类型 T => SomeOtherMonad[K] 的函数,如果是 monad,则将该函数应用于所有元素,然后将它们展平为您 Future[K].

def show(id: Long) = Action.async {
  db.run(entities.filter(_.id === id).result.headOption).flatMap {
    case None => templateFor("NEW_OBJECT")
    case Some(x) => Future(Ok(x))
  }

  def templateFor(code: String): Future[Result] =
    db.run(templates.filter(_.code === code).result.headOption).map {
      case None => InternalServerError("No template")
      case Some(x) => Ok(x)
    }
}