-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Future terminal operation documentation (#4447)
* Javadoc: document behavior of Future terminal operations Signed-off-by: Thomas Segismont <[email protected]> * Add andThen method to Future API This allows to guarantee order of execution for callbacks at the expense of creating new future instances. Signed-off-by: Thomas Segismont <[email protected]> * Extract futures documentation from index.adoc Signed-off-by: Thomas Segismont <[email protected]> * Futures documentation: add caution section about terminal operations Signed-off-by: Thomas Segismont <[email protected]> * Updates after review Signed-off-by: Thomas Segismont <[email protected]> * Fix doc (compilation failure) Signed-off-by: Thomas Segismont <[email protected]>
- Loading branch information
1 parent
37c6310
commit c57696a
Showing
6 changed files
with
286 additions
and
155 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
== Future results | ||
|
||
Vert.x 4 use futures to represent asynchronous results. | ||
|
||
Any asynchronous method returns a {@link io.vertx.core.Future} object for the result of the call: | ||
a _success_ or a _failure_. | ||
|
||
You cannot interact directly with the result of a future, instead you need to set a handler that will be called when the future completes and the result is available, like any other kind of event. | ||
|
||
[source,$lang] | ||
---- | ||
{@link examples.CoreExamples#exampleFuture1} | ||
---- | ||
|
||
NOTE: Vert.x 3 provides a callback-only model. | ||
To allow an easy migration to Vert.x 4 we decided that each asynchronous method has also a callback version. | ||
The `props` method above has also a version {@link io.vertx.core.file.FileSystem#props(java.lang.String, io.vertx.core.Handler)} with a callback as method argument. | ||
|
||
[CAUTION] | ||
==== | ||
Do not confuse _futures_ with _promises_. | ||
If futures represent the "read-side" of an asynchronous result, promises are the "write-side". | ||
They allow you to defer the action of providing a result. | ||
In most cases, you don't need to create promises yourself in a Vert.x application. | ||
<<_future_composition>> and <<_future_coordination>> provide you with the tools to transform and merge asynchronous results. | ||
However, if, in your codebase, you have legacy methods which use callbacks, you can leverage the fact that a promise extends {@link io.vertx.core.Handler io.vertx.core.Handler<io.vertx.core.AsyncResult>}: | ||
[source,$lang] | ||
---- | ||
{@link examples.CoreExamples#promiseAsHandler} | ||
---- | ||
==== | ||
|
||
[CAUTION] | ||
==== | ||
Terminal operations like `onSuccess`, `onFailure` and `onComplete` provide no guarantee whatsoever regarding the invocation order of callbacks. | ||
Consider a future on which 2 callbacks are registered: | ||
[source,$lang] | ||
---- | ||
{@link examples.CoreExamples#promiseCallbackOrder} | ||
---- | ||
It is possible that the second callback is invoked before the first one. | ||
If you need such guarantee, consider using <<_future_composition>> with {@link io.vertx.core.Future#andThen}. | ||
==== | ||
|
||
[#_future_composition] | ||
== Future composition | ||
{@link io.vertx.core.Future#compose(java.util.function.Function)} can be used for chaining futures: | ||
- when the current future succeeds, apply the given function, that returns a future. | ||
When this returned future completes, the composition succeeds. | ||
- when the current future fails, the composition fails | ||
[source,$lang] | ||
---- | ||
{@link examples.CoreExamples#exampleFutureComposition1} | ||
---- | ||
In this example, 3 operations are chained together: | ||
1. a file is created | ||
2. data is written in this file | ||
3. the file is moved | ||
When these 3 steps are successful, the final future (`future`) will succeed. | ||
However, if one of the steps fails, the final future will fail. | ||
Beyond this, {@link io.vertx.core.Future} offers more: `map`, `recover`, `otherwise`, `andThen` and even a `flatMap` which is an alias of `compose` | ||
[#_future_coordination] | ||
== Future coordination | ||
Coordination of multiple futures can be achieved with Vert.x {@link io.vertx.core.Future futures}. | ||
It supports concurrent composition (run several async operations in parallel) and sequential composition (chain async operations). | ||
{@link io.vertx.core.CompositeFuture#all} takes several futures arguments (up to 6) and returns a future that is | ||
_succeeded_ when all the futures are _succeeded_ and _failed_ when at least one of the futures is failed: | ||
|
||
[source,$lang] | ||
---- | ||
{@link examples.CoreExamples#exampleFutureAll1} | ||
---- | ||
|
||
The operations run concurrently, the {@link io.vertx.core.Handler} attached to the returned future is invoked upon completion of the composition. | ||
When one of the operation fails (one of the passed future is marked as a failure), the resulting future is marked as failed too. | ||
When all the operations succeed, the resulting future is completed with a success. | ||
|
||
Alternatively, you can pass a list (potentially empty) of futures: | ||
|
||
[source,$lang] | ||
---- | ||
{@link examples.CoreExamples#exampleFutureAll2} | ||
---- | ||
|
||
While the `all` composition _waits_ until all futures are successful (or one fails), the `any` composition | ||
_waits_ for the first succeeded future. {@link io.vertx.core.CompositeFuture#any} takes several futures arguments (up to 6) and returns a future that is succeeded when one of the futures is, and failed when all the futures are failed: | ||
|
||
[source,$lang] | ||
---- | ||
{@link examples.CoreExamples#exampleFutureAny1} | ||
---- | ||
|
||
A list of futures can be used also: | ||
|
||
[source,$lang] | ||
---- | ||
{@link examples.CoreExamples#exampleFutureAny2} | ||
---- | ||
|
||
The `join` composition _waits_ until all futures are completed, either with a success or a failure. | ||
{@link io.vertx.core.CompositeFuture#join} takes several futures arguments (up to 6) and returns a future that is succeeded when all the futures are succeeded, and failed when all the futures are completed and at least one of them is failed: | ||
|
||
[source,$lang] | ||
---- | ||
{@link examples.CoreExamples#exampleFutureJoin1} | ||
---- | ||
|
||
A list of futures can be used also: | ||
|
||
[source,$lang] | ||
---- | ||
{@link examples.CoreExamples#exampleFutureJoin2} | ||
---- | ||
|
||
=== CompletionStage interoperability | ||
|
||
The Vert.x `Future` API offers compatibility _from_ and _to_ `CompletionStage` which is the JDK interface for composable asynchronous operations. | ||
|
||
We can go from a Vert.x `Future` to a `CompletionStage` using the {@link io.vertx.core.Future#toCompletionStage} method, as in: | ||
|
||
[source,$lang] | ||
---- | ||
{@link examples.CompletionStageInteropExamples#toCS} | ||
---- | ||
|
||
We can conversely go from a `CompletionStage` to Vert.x `Future` using {@link io.vertx.core.Future#fromCompletionStage}. | ||
There are 2 variants: | ||
|
||
. the first variant takes just a `CompletionStage` and calls the `Future` methods from the thread that resolves the `CompletionStage` instance, and | ||
. the second variant takes an extra {@link io.vertx.core.Context} parameter to call the `Future` methods on a Vert.x context. | ||
|
||
IMPORTANT: In most cases the variant with a `CompletionStage` and a `Context` is the one you will want to use to respect the Vert.x threading model, since Vert.x `Future` are more likely to be used with Vert.x code, libraries and clients. | ||
|
||
Here is an example of going from a `CompletionStage` to a Vert.x `Future` and dispatching on a context: | ||
|
||
[source,$lang] | ||
---- | ||
{@link examples.CompletionStageInteropExamples#fromCS} | ||
---- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.