Search code examples
scalascala-collectionsconcurrent.futures

make scala future wait to modify a variable


I have been struck with a piece on how to obtain a listbuffer of strings in the case where the listbuffer happens to be constructed in a scala future called in a loop.

Here is a kiss example

def INeedThatListBuffer(): ListBuffer[String] = {

  var myCollections: ListBuffer[String] = new ListBuffer[String]()

  for (day <- daysInaWeek) {

    val myFuture: Future[String] = Future {
      // use 'day' do some stuff and get me a result
      ???
    }

    myFuture.onComplete {
      case Success(result) =>
        myCollections += result

    }
  }

  myCollections
}

My problem is that sometimes listBuffer is empty list and sometimes the content that I expected. Clearly, this method is complete before the future is evaluated.

Just to Add

  1. I don't want to used future.await
  2. Passing myCollections as Future obj does not work as there is no binding that myFuture must be complete before myCollections is evaluated.

Kindly help me out.

Thanks


Solution

  • This returns a future. If you don't care about waiting for it to be complete, you can always access the underlying value using .value:

    def INeedThatListBuffer(): Future[ListBuffer[String]] = {
    
      def buildFutureFromDay(day: String): Future[String] = Future { ??? }
    
      Future
        .sequence(daysInAWeek.map(buildFutureFromDay))
        .map(_.foldLeft(ListBuffer[String]())(_ += _))
    
    }