在单个 Play 操作中进行独立的 Slick 查询
Making independent Slick queries inside of single Play action
我有异步播放 Action
,它使用 Slick 从数据库中检索数据。显然,Slick 使用 Future
s 来避免阻塞:
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
,所以整个Action
returnsFuture[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)
}
}
我有异步播放 Action
,它使用 Slick 从数据库中检索数据。显然,Slick 使用 Future
s 来避免阻塞:
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
,所以整个Action
returnsFuture[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)
}
}