[英]Scala adding elements to seq and handling futures, maps, and async behavior
我仍然是scala的新手,還不太了解Futures / Maps / Flatmaps / Seq的概念以及如何正確使用它們。
這就是我想要做的(偽代碼):
def getContentComponents: Action[AnyContent] = Action.async {
contentComponentDTO.list().map( //Future[Seq[ContentComponentModel]] Get all contentComponents
contentComponents => contentComponents.map( //Iterate over [Seq[ContentComponentModel]
contentComponent => contentComponent.typeOf match { //Match the type of the contentComponent
case 1 => contentComponent.pictures :+ contentComponentDTO.getContentComponentPicture(contentComponent.id.get) //Future[Option[ContentComponentPictureModel]] add to _.pictures seq
case 2 => contentComponent.videos :+ contentComponentDTO.getContentComponentVideo(contentComponent.id.get) //Future[Option[ContentComponentVideoModel]] add to _.videos seq
}
)
Ok(Json.toJson(contentComponents)) //Return all the contentComponents in the end
)
}
我想將Future[Option[Foo]]
到contentComponent.pictures: Option[Seq[Foo]]
如下所示:
case 2 => contentComponent.pictures :+ contentComponentDTO.getContentComponentPicture(contentComponent.id.get) //contentComponent.pictures is Option[Seq[Foo]]
最后通過json將整個contentComponent返回到前端。
我知道這最終可能與實際代碼相去甚遠,但我希望您能理解。 謝謝!
我將忽略您的代碼,而將重點放在簡短的意義上:
我想將Future [Option [Foo]]添加到contentComponent.pictures:Option [Seq [Foo]],如下所示:
讓我們這樣做,着重於代碼的可讀性:
// what you already have
val someFuture: Future[Option[Foo]] = ???
val pics: Option[Seq[Foo]] = contentComponent.pictures
// what I'm adding
val result: Future[Option[Seq[Foo]]] = someFuture.map {
case None => pics
case Some(newElement) =>
pics match {
case None => Some(Seq(newElement)) // not sure what you want here if pics is empty...
case Some(picsSequence) => Some(picsSequence :+ newElement)
}
}
為了顯示flatMap
的示例,假設您需要另一個將來的result
將來的result
,只需執行以下操作:
val otherFuture: Future[Any] = ???
val everything: Future[Option[Seq[Foo]]] = otherFuture.flatmap { otherResult =>
// do something with otherResult i.e., the code above could be pasted in here...
result
}
我的回答將嘗試幫助解決一些概念性子問題,這些子問題構成了您的整體較大問題的一部分。
flatMap
和for-yield
flatMap
的要點之一是幫助解決Doom金字塔的問題。 當您將結構嵌套在結構中時,會發生這種情況。
doA().map { resultOfA =>
doB(resultOfA).map { resolutOfB =>
doC(resultOfB).map { resultOfC =>
...
}
}
}
如果您使用for-yield
,則可以直接使用flatMap
,它可以讓您
弄平金字塔
這樣您的代碼看起來更像線性結構
for {
resultOfA <- doA
resultOfB <- doB(resultOfA)
resultOfC <- doC(resultOfB)
...
} yield {...}
在軟件工程中有一條經驗法則,即深層嵌套的結構更難調試和推理,因此我們努力使嵌套最小化。 您將尤其在處理Futures
時遇到此問題。
Future
映射與序列映射
映射通常是首先考慮序列上的迭代,這可能會導致對迭代 Future
的映射進行理解。 我的建議是,在嘗試理解Futures
, Options
等的映射時不要使用迭代概念。在這些情況下,最好將映射視為破壞結構的過程,這樣您才能了解結構內部的元素。 可以將映射可視化為
打破核桃的殼,以便獲得內部的美味核仁,然后重建殼。
Futures
和單子
當您嘗試了解有關Futures
更多信息時,當您開始處理諸如Future[Option[SomeType]]
類的類型時,您將不可避免地偶然發現有關monad的文檔,其隱晦術語可能會嚇跑您。 如果發生這種情況,將Monad( Future
是特定實例)簡單地考慮可能會有所幫助。
您可以堅持
for-yield
這樣就可以得到可口的核桃仁,同時避免厄運金字塔。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.