我仍然是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返回到前端。
我知道这可能与最终的实际代码相差甚远,但我希望你能得到这个想法。谢谢!
答案 0 :(得分:1)
我的回答将尝试帮助解决构成整体较大问题的一些概念性子问题。
flatMap
和for-yield
flatMap
的一个要点是帮助解决Pyramid of 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
和monads
当您尝试了解有关Futures
的更多信息时以及当您开始处理Future[Option[SomeType]]
等类型时,您将不可避免地
偶然发现有关monad及其神秘术语的文档可能会吓跑你。如果发生这种情况,可能有助于将monad(其中Future
是特定实例)简单地视为
你可以坚持
for-yield
的东西,这样你就可以进入。{1}} 美味的核桃仁,同时避免了厄运的金字塔。