make scala future wait to modify a variable

485 views Asked by At

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

2

There are 2 answers

1
adrice727 On BEST ANSWER

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]())(_ += _))

}  
0
Selvaram G On

You need to await at some point. Either await for each of the futures to get resolved or change the ListBuffer[String] to ListBuffer[Future[String]] and await on the whole buffer later.

val myFutureCollection: ListBuffer[Future[String]] = new ListBuffer[Future[String]]()
val myFuture: Future[String] = Future(???)

myFutureCollection += myFuture

val eventualBuffer: Future[ListBuffer[String]] = Future.sequence(myFutureCollection)
val buffer: ListBuffer[String] = Await.result(eventualBuffer, 2 seconds)

P.S: You can val instead of var for the list buffer as it is already mutable.