Support for promises. If an operation cannot return a value immediately without blocking, it may instead return a promise of the value. A promise is an object that represents the return value or the thrown exception that the operation eventually produces. Such an operation is sometimes called a long-running operation.
This module provides following abstractions:
Completable
interface abstracts objects which
promise one or more values, accommodating the possibility
of failure.Term
interface abstracts Completable
s that may
be combined to form a compound promise that produces
multiple values.Promise
class, a Completable
that produces a
single value, or fails.Deferred
class, providing support for operations
which return instances of the Promise
interface.Future
class, providing support for clients who
wish to block which awaiting a Promise
.A Promise
exists in one of three states:
The method Completable.onComplete()
allows interested
parties to be notified when the promise makes a
transition from the promised state to the fulfilled or
the rejected state:
Promise<Document> promise = queryDocumentById(id); promise.onComplete { (d) => print("Got the document: " + d.title); (e) => print("Document was not received: " + e.message); };
The first function is called the onFulfilled
callback and
the second function is called the onRejected
callback.
The onRejected
function is always optional.
A Deferred
object is a factory that provides an
instance of the Promise
class and manages its lifecycle,
providing operations to force its transition to a
fulfilled or rejected state.
The instance of Deferred
should remain private to the
long-running operation, only the Promise
should be
exposed to the caller.
The Promise
of a deferred can be retrieved from its
promise field:
value deferred = Deferred<String>(); return deferred.promise;
The Deferred
object implements the Resolver
interface
which provides two methods for controlling the state of the
promise:
Throwable
.For example:
value deferred = Deferred<String>(); void doOperation() { try { String val = getValue(); deferred.fulfill(val); } catch (Throwable e) { deferred.reject(e); } }
When composition is needed the method Completable.compose()
should be used instead of the Completable.onComplete()
method.
When invoking the Completable.compose()
method the
onFulfilled
and onRejected
callbacks can return a value.
The compose()
method returns a new promise that will be
fulfilled with the value of the callback. This promise will
be rejected if the callback invocation fails.
For example:
Promise<Integer> promiseOfInteger = promiseOfInteger(); Promise<String> promiseOfString = promiseOfInteger.compose((i) => i.string); promiseOfString.compose((s) => print("Completed with " + s));
Or, more concisely:
promiseOfInteger() .compose((i) => i.string) .compose((s) => print("Completed with " + s));
Promises can be composed into a single promise that is fulfilled when every one of the individual composed promises is fulfilled. If one of the promise is rejected then the composed promise is rejected.
Promise<String> promiseOfInteger = promiseOfString(); Promise<Integer> promiseOfString = promiseOfInteger(); (promiseOfInteger and promiseOfString).onCompletion { (i, s) => print("All fulfilled"); (e) => print("One failed"); };
Notice that:
Promise
but Completable
.always()
methodThe always() method of a promise allows a single callback to be notified when the promise is fulfilled or rejected.
Promise<Document> promise = queryDocumentById(id); promise.always { void (Document|Throwable result) { switch (result) case (Document) { print("Fulfilled"); } case (Throwable) { print("Rejected"); } }; };
always()
is most useful for implementing a finally clause
in a chain of promises.
Deferred
can be transitioned with a promise instead of a
value:
Deferred<String> deferred1 = getDeferred1(); Deferred<String> deferred2 = getDeferred2(); deferred1.fulfill(deferred2);
Similarly the callback may return a promise instead of a value:
Deferred<String> deferred = Deferred<String>(); promise.compose((s) => deferred.promise);
Sometimes it is convenient to block until a promise is
resolved. For this purpose a promise may be transformed
into a Future
via the attribute Promise.future
:
Promise<String> promise = getPromise(); Future<String> future = promise.future; String|Throwable resolution = future.get(10k); //wait for 10 sec
Keep in mind that this is not the usual way you should use promises as this defeats the non blocking model. Nevertheless there are times when it is useful to block, for instance, in unit tests.
The implementation is thread safe and uses a non blocking
algorithm for maintaining the state of a Deferred
object.
This module is loosely based upon the A+ specification, with the following differences:
then()
method is named compose()
in Ceylonthen()
must return before
onFulfilled
or onRejected
is called is not
implemented. Therefore the invocation occurs inside the
invocation of compose()
.Packages | |
ceylon.promise |
Dependencies | ||
java.base | 7 |
Aliases | |
Promisable | Source Codeshared Promisable<out Result> |
Interfaces | |
Completable | Source Codeshared Completable<out Value> |
Future | Source Codeshared Future<out Value> A future value. |
Promised | Source Codeshared Promised<out Value> An object that provides a |
Resolver | Source Codeshared Resolver<in Value> Something that can go through a transition and is meant to be be fulfilled or rejected. |
Term | Source Codeshared Term<out Element,out T> A term allows a |
Classes | |
Deferred | Source Codeshared Deferred<Value> The deferred class is the primary implementation of the
The promise is accessible using the The deferred can either be fulfilled or rejected via the
|
Promise | Source Codeshared abstract Promise<out Value> A promise represents a value that may not be available yet.
The primary method for interacting with a promise is its
|