Federico Lenzi
Federico Lenzi

Reputation: 1612

Why doesn't onComplete wait for Promise.success in the code in Scala?

I'm reading about Futures and Promises in Scala and wrote the following code:

def printSomething(): Future[String] = {
  val p = Promise[String]
  val sayHello = future {
    Thread.sleep(1000)
    p.success("hello")
  }
  p.future
}

def main(args: Array[String]) {
  val something: Future[String] = printSomething()
  something onComplete {
    case Success(p) => println(p)
  }
}

The problem is the onComplete callback doesn't print anything (unless I debug it).

Wouldn't the onComplete have to wait for the p.success("hello") in the printSomething ?

Upvotes: 3

Views: 1480

Answers (3)

Nicolas Rinaudo
Nicolas Rinaudo

Reputation: 6168

As other people have stated, your execution terminates before your future has had a chance to run. I feel, however, that adding a hard-coded sleep call isn't the cleanest solution, and that waiting for the future to complete (with a timeout, to prevent your code from getting stuck) is preferable:

Await.ready(something, Duration(2000, MILLISECONDS))

This will wait at most 2000 milliseconds for something to be complete, or fail otherwise.

Upvotes: 2

cmbaxter
cmbaxter

Reputation: 35453

My guess is that this has to do with the ExecutionContext you are using daemon threads and thus terminating when your main gets past the onComplete. If you add a sleep after the onComplete, you should get what you want. A slightly modified version of your code showing this:

import concurrent._
import ExecutionContext.Implicits._

object PromTest {
  def printSomething(): Future[String] = {
    val p = Promise[String]
    val sayHello = future {
      Thread.sleep(1000)
      p.success("hello")
    }
    p.future
  }

  def main(args: Array[String]) {
    val something: Future[String] = printSomething()
    something onComplete {
      case result => println(result)
    }
    Thread.sleep(2000)
  }
}

Upvotes: 6

Jean-Philippe Pellet
Jean-Philippe Pellet

Reputation: 60006

Your app exits before your promise is completed. At the end of your main method, just add something like Thread.sleep(2000) and you'll see your result.

Upvotes: 1

Related Questions