Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Promise

In Scala, a Promise is a writable, single-assignment container which completes a Future. Essentially, Promise and Future are two sides of the same coin: while Future provides a way to read a value that may not yet exist, Promise provides a way to write that value once it becomes available. This mechanism is particularly useful in scenarios where you need to manually complete a Future based on the outcome of some computation or asynchronous operation.

Basic Usage of Promise

Here's how you can create and use a Promise in Scala:

  1. Creating a Promise

First, you need to import the necessary classes:

import scala.concurrent.{Promise, Future}
import scala.concurrent.ExecutionContext.Implicits.global

Then, create a Promise:

val promise: Promise[Int] = Promise[Int]()
  1. Obtaining the Future from a Promise

You can obtain a Future associated with a Promise. This Future is completed when the Promise is fulfilled.

val future: Future[Int] = promise.future
  1. Completing a Promise

A Promise can be completed with a value or an exception. Completing the Promise also completes its associated Future.

// Completing the promise with a value
promise.success(42)

// Alternatively, completing the promise with a failure
// promise.failure(new RuntimeException("Failure"))
  1. Using the Future

You can work with the Future obtained from a Promise just like any other Future. For example, you can add callbacks to handle completion:

future.onComplete {
  case Success(value) => println(s"The result is $value")
  case Failure(exception) => println(s"Failed with $exception")
}

Example: Asynchronous Computation

Here's a more concrete example, demonstrating how a Promise can be used to wrap an asynchronous computation, such as a network request:

def asyncNetworkRequest(url: String): Future[String] = {
  val promise = Promise[String]()

  // Simulate an asynchronous network request
  global.execute(() => {
    try {
      // Simulating request delay
      Thread.sleep(1000)
      promise.success(s"Response from $url")
    } catch {
      case e: Exception => promise.failure(e)
    }
  })

  promise.future
}

val url = "http://example.com"
val responseFuture: Future[String] = asyncNetworkRequest(url)

responseFuture.onComplete {
  case Success(response) => println(response)
  case Failure(exception) => println(s"Request failed: $exception")
}

In this example, asyncNetworkRequest simulates making an asynchronous network request. It uses a Promise to represent the eventual result of the request. The Promise is completed with a success or failure once the simulated request finishes, and the associated Future is used to handle the response.