[英]Play Framework / Dependent Future Composition
我試圖做幾個相關的Slick / DB調用,然后在旋轉模板中顯示結果數據。
def show(slug: String) = Action.async { implicit rs =>
for {
f <- fooDAO.findBySlug(slug) // f is of type Option[foo]
fid <- f.flatMap(a => a.id.map(b => b)) // fid is of type Long
b <- barDAO.findByFooId(fid) // b is of type Seq[bar]
} yield {
f.map {
case Some(f) => Ok(views.html.foobar(f, b))
case _ => NotFound
}
}
}
我首先需要獲取“ ID”,然后才能查詢其他相關數據。 編譯器現在產生此錯誤:
play.sbt.PlayExceptions$CompilationException: Compilation error[type mismatch;
found : scala.concurrent.Future[Option[play.api.mvc.Result]]
required: Option[?]]
任何幫助將不勝感激。
您的代碼有一個根本的缺陷,就是您在同一理解中混用了Option
和Seq
理解力將適用於相同的“容器”類型,這將是yield
的結果表示
例如,如果將多個Option
組合在一起,則會得到一個Option
;如果將Seq
組合在一起,則會得到一個Seq
。
在這種情況下,您可以通過將Option
(foo)轉換為Seq
來解決問題(如果foo為None
則為空,否則為1個元素)。
最終結果將是
val results: Seq[(Foo, Bar)] =
for {
f <- fooDAO.findBySlug(slug).toSeq // f is of type Seq[Foo]
b <- barDAO.findByFooId(f.id) // b is of type Seq[Bar]
} yield (f, b)
但是我想這不是您所需要的。 我想您想獲得與檢索到的Foo
相關聯的所有Bar
(如果有),並將其與您的模板一起呈現。 如果該slug
不存在Foo
則需要NotFound
。
我們可以這樣
def show(slug: String) = Action.async { implicit rs =>
val f = fooDAO.findBySlug(slug) // f is of type Option[Foo]
f.fold(
NotFound,
foo => Ok(views.html.foobar(foo, barDAO.findByFooId(foo.id))
)
}
您可以通過定義一種支持方法使其更加明確
def show(slug: String) = Action.async { implicit rs =>
def barsOf(f: Foo): Seq[Bar] = barDAO.findByFooId(f.id)
val f = fooDAO.findBySlug(slug) // f is of type Option[Foo]
f.fold(
NotFound,
foo => Ok(views.html.foobar(foo, barsOf(foo))
)
}
了解您要在此處實現的目標有點棘手,但是如果整個事情都基於findbySlug
返回Future[Option[Foo]]
的結果,並且如果那個Option
為None
話,最終結果是NotFound
,那么您的yield
應該可能只是:
...
} yield {
f.fold(NotFound)(foo => Ok(views.html.foobar(foo, b)))
}
Option[T]
是用於數據檢索和控制流的理想類型,但是對其進行模式匹配幾乎永遠不是正確的方法 。 fold
的使用感覺很簡潔。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.