As I know, Future
is read-only and Promise
is write-once data structure.
We need a Promise
to complete a Future
For example,
object Lie extends Throwable
val lie = Future { throw Lie }
val guess = Promise[String]()
lie.onComplete { case Success(s) => guess.success("I knew it was true!")
case Failure(t) => guess.failure("I knew it was lie")}
// return type: Unit
guess.future.map(println)
// res12: scala.concurrent.Future[Unit] = List()
// I knew it was lie!
// Requires Promise to chain Future with exception
But, I can't understand why we need to have both Future
and Promise
I guess Promise
is required because of Future.onComplete
signature
Since Future.onComplete
return type is Unit
,Future
with possible exceptions cannot be chained
I assume Promise
was introduced to overcome this limitation
But why not just change the signature of Future.onComplete
?
Changing the return type of Future.onComplete
as Future[T]
will enable chaining on Future
with exception
and then, Future
does not need Promise
For example, code above can be changed into
val lie = Future { throw Lie }
lie.onComplete {
case Success(s) => "I knew it was true!"
case Failure(t) => "I knew it was lie!"
}.map(println)
//onComplete return type is Future[String]
My question is
1) am I right? does Future
not need Promise
, If onComplete signature is changed from Unit
to Future[T]
?
2) Why Future and Promise are divided in the first place ?
UDPATE
Thanks to the repliers, Now I understand the purpose of Promise. It wasn't actually for Future
chaining
If I may, can I ask you
Why onComplete
returns Unit
??
It can actually return Future[T]
to enable chaining Future easily
For example
Future { throw Error }.onComplete {
case Success(s) => "Success"
case Failure(t) => throw Error
}.onComplete {
case Success(s) => "Success"
case Failure(t) => throw Error
}. ...
Future.apply[T](block: => T): Future[T]
is syntactic sugar forFuture.unit.map(_ => block)
[1]A
Future
represents a value which may or may not be currently available.A
Promise
represents the obligation to provide such a value at some point.Having separate entities for
Future
(for reads) andPromise
(for writes) means that it is easy to reason about capabilities:When a Future is a parameter, it is a request to have some value at some point and when it is used as a return type, it's a response which may not be currently available.
When a Promise is a parameter, it is the "consumption" of responsibility of producing some value at some point, and when it is used as a return type it is the "production" of responsibility to produce the value at some point.
All in all, being able to reason about capabilities, especially in asynchronous, or even concurrent programs, is extremely valuable.
Most of the time Promises need not be used, since that is transparently handled by the Future-combinators—but when integrating with third party software or networking libraries it can be extremely useful.
For more information about interesting new features in Scala 2.12, have a look here.
1: Where
Future.unit
is defined as:val unit: Future[Unit] = Future.successful(())
You're mixing things up a little. Let's clarify.
A
Future[T]
represents a computation which will complete in the future. That is, you passFuture.apply
a function which will execute on a thread assigned by someExecutionContext
you define.Now, on the other hand, a
Promise[T]
is a way to create aFuture[T]
, without actually creating aFuture[T]
. A good example for this would be theFuture.successful
method (which will internally consumePromise.successful
):This requires no
ExecutionContext
and no queuing if any additional resources. It's merely a convenience wrapper that allows you to "artificially" create aFuture[T]
.No.
Future
cannot cover the use cases ofPromise
.Promise
has its own value. You cannot replaceFuture
withPromise
.Future
represents a computation which is available at a later point of time. You can get the result usingonComplete
once the future execution is complete and you can compose futures usingmap
,flatMap
,recover
andrecoverWith
.Future is read-only
But
Promise
is different.That means you are promising user something which you do not have right now.
So you want to keep the user waiting till you have the thing which you will give it to user. Thats when you do
p.future
and generate a future so that user can wait for the result using the future.Once you have the result which you promised to give the user, You give to user by making the future a
success
orfailure
when something bad happens (i.e by doingp.complete
).Creating future using Future companion object
Future can be created by using
Future.apply
also. In this case future created would be complete once the computation inside the future finishes.