Cómo conseguir efectos de whenComplete y thenCompose combinado?

Zigzagoon:

Estoy tratando de llegar a un CompletableFuture con los efectos combinados de whenCompletey thenCompose, específicamente:

  1. Devuelve un CompletionStagelugar de sólo un resultado, similar a thenCompose.
  2. Ejecuta incluso cuando se complete la etapa anterior con carácter excepcional, similares a whenComplete, y no se detiene la excepción se propague.

Este post está cerca de lo que estoy tratando de lograr, pero no quiero usar handleque oculta la excepción. Gracias por cualquier idea.

repollo:

No creo CompletionStageni CompletableFutureproporciona ningún método sencillo para esto. Sin embargo, la combinación handlecon thenComposedebe hacer lo que quiera, si entiendo correctamente a sus necesidades.

Una handleetapa se ejecuta si la etapa principal ha completado normalmente o, excepcionalmente, y le da acceso al resultado o error, respectivamente. A partir de esta etapa se podía volver otra CompletionStageque, o bien se ha completado con normalidad o, excepcionalmente, en función de qué argumentos la handleetapa recibe.

handle((T result, Throwable error) -> {
    if (error != null) {
        return CompletableFuture.<T>failedStage(error);
    } else {
        return processResult(result); // returns CompletionStage<T>
    }
});

Ahora usted tiene una CompletionStage<CompletionStage<T>>. Ahora llevamos a cabo una operación de mapa plano mediante la invocación thenCompose:

thenCompose(Function.identity());

Lo que nos da una CompletionStage<T>. Esto CompletionStage<T>será lo que sea ejemplo fue devuelto por handle. Si esa instancia fue una etapa fallidas y se sigue la excepción se propaga; de lo contrario, el resultado se pasa a cualquier etapa depende de la thenComposeetapa y el proceso continúa normalmente.

Esto se puede ver con el siguiente ejemplo:

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;

public class Main {

    public static void main(String[] args) {
        methodThatReturnsCompletionStage()
                .handle((result, error) -> {
                    if (error != null) {
                        return CompletableFuture.<String>failedStage(error);
                    } else {
                        return processResult(result);
                    }
                })
                .thenCompose(future -> {
                    System.out.println("#thenCompose invoked");
                    return future; // Identity function
                })
                .thenApply(result -> {
                    System.out.println("#thenApply invoked");
                    return result; // Identity function (exists to show intermediary stage)
                })
                .whenComplete((result, error) -> {
                    System.out.println("#whenComplete invoked");
                    if (error != null) {
                        error.printStackTrace(System.out);
                    } else {
                        System.out.println(result);
                    };
                });
    }

    private static CompletionStage<String> methodThatReturnsCompletionStage() {
        return CompletableFuture.completedStage("Hello");
        // return CompletableFuture.failedStage(new RuntimeException("OOPS"));
    }

    private static CompletionStage<String> processResult(String result) {
        return CompletableFuture.completedFuture(result + ", World!");
    }

}

Esto resultará en cada etapa que se invoca y una salida de Hello, World!. Pero si se cambia methodThatReturnsCompletionStage()para volver al escenario fallado entonces thenApplyse salta (porque el futuro ha fallado) y se le da a la excepción whenComplete(que, al igual que handle, se invoca tanto para la finalización normal o excepcional).

Nota: Todo lo anterior se utiliza la CompletionStageinterfaz directamente, sino mediante CompletableFuturefunciona igual de bien (y puede ser preferible).

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=227164&siteId=1
Recomendado
Clasificación