Search code examples
scalafutureyield

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


Consider the below code snippet:

In this, I am trying to get values from future using 'For - yield' comprehension. Now in yield method, I need to do a check which makes the call to a function fallbackResult which returns a future and hence return type of getData becomes 'Future[Future[Option[Int]]]' rather than 'Future[Option[Int]]'. How could I make this with a better way? (I did use Map & FlatMap's, but the code little ugly due to nesting Maps and FlatMaps)

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
}

Solution

  • Id put the code inside the for-coprehension:

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