Scala:处理从 Yield 返回的 Future 以避免未来的未来的更好方法

Scala : Better way to handle returning Future from Yeild to avoid future of future

考虑以下代码片段:

在此,我尝试使用 'For - yield' 理解从未来获取价值。现在在 yield 方法中,我需要做一个检查,使调用 fallbackResult 函数成为 return 的未来,因此 return 类型的 getData 变为 'Future[Future[Option[Int]]]' 而不是 'Future[Option[Int]]' .我怎样才能用更好的方法做到这一点? (我确实使用了 Map & FlatMap,但是由于嵌套了 Maps 和 FlatMap,代码有点难看)

def getData(): Future[Future[Option[Int]]] = {

  /* These are two future vectors. Ignore the Objects */

  val substanceTableF: Future[Vector[OverviewPageTableRowModel]] = getSubstanceTable(substanceIds, propertyId, dataRange)
  val mixtureTableF: Future[Vector[OverviewPageTableRowModel]] = getMixtureTableForSubstanceCombination(substanceIds, propertyId, dataRange)

  /* I have put for yeild to get values from futures.*/
  for {
      substanceTable <- substanceTableF
      mixtureTable <- mixtureTableF
  } yield {
      if(substanceTable.isEmpty && mixtureTable.isEmpty) {
          val resultF = fallbackResult()
          resultF.map(result => {Some(result)})
      } else {
          Future.successful(Some(100))
      }
  }
}

private def fallbackResult(): Future[Int] = { 
    // This method returns future of int
}

我将代码放在 for-coprehension 中:

for {
   substanceTable <- substanceTableF
   mixtureTable <- mixtureTableF 
   result <- {
     if (substanceTable.isEmpty && mixtureTable.isEmpty)
       fallbackResult()
     else
       Future.successful(Some(100))
   }
 } yield result

有很多方法可以解决这个问题,但关键是将您的 yield 逻辑转移到您的 for 理解中。一种方法如下:

for {
  substanceTable <- substanceTableF
  mixtureTable <- mixtureTableF
  result <- (substanceTable.headOption orElse mixtureTable.headOption)
               .map(_ => Future.successful(Some(100)))
               .getOrElse(fallbackResult)
} yield result