[英]A simple recipe for conditional webservice activity in Action.async in a play controller
我正在尝试将scala和playframework用作具有RESTful HTTP API的数据库服务器的前端。
我的问题是控制器的逻辑需要先查询数据库,然后作出决定,然后再对数据库进行2次更新。 目前,我被困在aync未来的地狱中,看不到我的出路。
这是我要执行的操作的伪代码概述:
def myMethod = Action.async {
if (A exists in DB) {
get A.value from the db
if (A.value == x) {
update A.value
insert B
if (success) Status(200)
else Status(500)
}
else Status(409)
}
else Status(404)
}
任何建议或当前教程的链接将不胜感激。
看一下《 撰写相关期货》 ,它有很多好话要说,同时也要承认困难(尤其是在混合Future
和Option
)。
这是一些(粗略的)代码,可以模拟您描述的内容。 正如Scala中经常出现的那样,有很多方法可以做到这一点( map
, flatMap
, for
理解等),并且某些东西看起来比其他东西更容易理解。
import scala.concurrent.Future
// Future.successful looks nicer IMO when aliased
import scala.concurrent.Future.{successful => immediate}
// A mock item
case class Thing(value: Int)
// A mock service, note that get returns an option
// to cover the not-existing case
object Service {
def get(id: Int): Future[Option[Thing]] = ???
def update(id: Int, item: Thing): Future[Thing] = ???
def create(item: Thing): Future[Thing] = ???
}
def myMethod(id: Int) = Action.async { implicit request =>
val x = 666 // um, or whatever?
Service.get(id).flatMap {
case Some(thing) if thing.value == x =>
(for {
// NB: We don't care about the results so using _ here
_ <- Service.update(x, Thing(1001))
_ <- Service.create(Thing(1002))
} yield Ok) recover {
// Handle the error case from one of the futures
case e => InternalServerError(e.getMessage)
}
case Some(thing) => immediate(Conflict(thing.toString))
case None => immediate(NotFound)
}
}
注意事项:
flatMap
和a混合使用以for
理解,这可能是有问题的样式,但我认为这样看起来会更好 Status(x)
Future.successful
(别名为immediate
),这是一个没有未来的运
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.