Как получить комбинированные эффекты whenComplete и thenCompose? - PullRequest
4 голосов
/ 20 июня 2019

Я пытаюсь создать CompletableFuture с комбинированными эффектами whenComplete и thenCompose, в частности:

  1. Возвращает CompletionStage вместо просто результата, похожего на thenCompose.
  2. Выполняется, даже если предыдущий этап завершается исключительно, аналогично whenComplete, и не мешает распространению исключения.

Этот пост близко к тому, чего я пытаюсь достичь, но я не хочу использовать handle, который скрывает исключение.Спасибо за любые идеи.

1 Ответ

2 голосов
/ 20 июня 2019

Я не верю, что CompletionStage или CompletableFuture предоставляют какой-либо один метод для этого.Однако сочетание handle с thenCompose должно делать то, что вы хотите, если я правильно понимаю ваши требования.

A handle этап выполняется независимо от того, завершился ли родительский этап нормально или исключительно, и дает вам доступ крезультат или ошибка соответственно.На этом этапе вы можете вернуть еще один CompletionStage, который будет либо завершен нормально, либо исключительно, в зависимости от того, какие аргументы получает этап handle.

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

Теперь у вас есть CompletionStage<CompletionStage<T>>.Теперь мы выполняем операцию плоской карты, вызывая thenCompose:

thenCompose(Function.identity());

, что дает нам CompletionStage<T>.Это CompletionStage<T> будет тем экземпляром, который был возвращен handle.Если этот экземпляр был ошибочным этапом, то исключение все еще распространяется;в противном случае результат передается на любой этап, зависящий от этапа thenCompose, и обработка продолжается в обычном режиме.

Это можно увидеть на следующем примере:

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!");
    }

}

Это приведет ккаждая вызванная стадия и вывод Hello, World!.Но если вместо этого переключить methodThatReturnsCompletionStage(), чтобы вернуть сбойный этап, thenApply пропускается (потому что будущее провалилось), и исключение составляет whenComplete (который, как и handle, вызывается как для обычного, так и исключительного).завершение).

Примечание: Все вышеперечисленное использует интерфейс CompletionStage напрямую, но использование CompletableFuture работает так же (и может быть предпочтительнее).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...