Scala Promises are a powerful concurrency tool used for handling asynchronous operations. They provide a way to represent a value that may not yet be available but will be computed in the future. Promises work hand-in-hand with Scala Futures to manage concurrent computations efficiently.
A Promise is a writable, single-assignment container that completes a Future. While Futures are read-only and can be composed, Promises allow you to control when and how a Future is completed. This makes them particularly useful in scenarios where you need to manage the completion of asynchronous operations manually.
To create a Promise in Scala, you can use the Promise[T]
class, where T
is the type of the value that will be computed. Here's a simple example:
import scala.concurrent.Promise
import scala.concurrent.ExecutionContext.Implicits.global
val promise = Promise[String]()
val future = promise.future
future.onComplete {
case Success(result) => println(s"Result: $result")
case Failure(ex) => println(s"Error: ${ex.getMessage}")
}
// Later, complete the promise
promise.success("Hello, Scala Promises!")
In this example, we create a Promise of type String, obtain its associated Future, and set up a completion handler. Later, we complete the Promise with a success value.
Promises are particularly useful in the following scenarios:
There are several ways to complete a Promise:
success(value: T)
: Completes the Promise with a successful valuefailure(exception: Throwable)
: Completes the Promise with an exceptioncomplete(result: Try[T])
: Completes the Promise with either a success or failureHere's a more advanced example demonstrating how to implement a timeout using Promises and Scala Futures:
import scala.concurrent.{Future, Promise}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
def withTimeout[T](future: Future[T], timeout: Duration): Future[T] = {
val promise = Promise[T]()
// Set up the main future
future.onComplete(promise.tryComplete)
// Set up the timeout
akka.pattern.after(timeout, using = global) {
Future.successful(promise.tryFailure(new TimeoutException("Operation timed out")))
}
promise.future
}
// Usage
val slowOperation = Future {
Thread.sleep(5000)
"Operation completed"
}
val result = withTimeout(slowOperation, 3.seconds)
result.onComplete {
case Success(value) => println(s"Result: $value")
case Failure(ex) => println(s"Error: ${ex.getMessage}")
}
This example demonstrates how to create a function that adds a timeout to any Future operation using Promises. It showcases the power and flexibility of Promises in managing complex asynchronous scenarios.
By mastering Scala Promises, you can effectively manage complex asynchronous operations and build more responsive and efficient Scala applications. They provide a powerful tool in your concurrency toolkit, complementing other Scala features like Futures and Parallel Collections.