All Downloads are FREE. Search and download functionalities are using the official Maven repository.

x-core.4.5.8.source-code.futures.adoc Maven / Gradle / Ivy

There is a newer version: 5.0.0.CR1
Show newest version
== 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}:

[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.Future#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.

On success, the `resultAt` method guarantees the results in the same order specified in the call to `Future.all`. In the example above, regardless of which item completed first, the `httpServer` result can be accessed using `resultAt(0)` and the `netServer` result can be accessed using `resultAt(1)`.

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.Future#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.Future#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}
----




© 2015 - 2024 Weber Informatics LLC | Privacy Policy