簡體   English   中英

Scala向seq添加元素並處理期貨,地圖和異步行為

[英]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
}

我的回答將嘗試幫助解決一些概念性子問題,這些子問題構成了您的整體較大問題的一部分。

flatMapfor-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的映射進行理解。 我的建議是,在嘗試理解FuturesOptions等的映射時不要使用迭代概念。在這些情況下,最好將映射視為破壞結構的過程,這樣您才能了解結構內部的元素。 可以將映射可視化為

打破核桃的殼,以便獲得內部的美味核仁,然后重建殼。

Futures和單子

當您嘗試了解有關Futures更多信息時,當您開始處理諸如Future[Option[SomeType]]類的類型時,您將不可避免地偶然發現有關monad的文檔,其隱晦術語可能會嚇跑您。 如果發生這種情況,將Monad( Future是特定實例)簡單地考慮可能會有所幫助。

您可以堅持for-yield這樣就可以得到可口的核桃仁,同時避免厄運金字塔。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM