java многовложенный CompletionStage эквивалентен flatMap?

Итак, учитывая, что у меня есть следующий пример:

CompletionStage<String> tokenFuture = getToken();

CompletionStage<CompletionStage<CompletionStage<CompletionStage<Boolean>>>> result = tokenFuture.thenApply(token -> {

    WSRequest request = ws.url(url).setHeader("Authorization", "Bearer " + token);

    CompletionStage<WSResponse> response = request.post(json);

    return response.thenApply(r -> {
        if (r.getStatus() == 201) {
            return CompletableFuture.supplyAsync(() -> CompletableFuture.supplyAsync(() -> true));
        } else {
            return getToken().thenApply(t -> {
                WSRequest req = ws.url(url).setHeader("Authorization", "Bearer " + t);
                return req.post(json).thenApply(b -> b.getStatus() == 201);
            });
        }
    });

});

Моя проблема связана со всем CompletionStage<CompletionStage<CompletionStage<CompletionStage<Boolean>>>> мультивложенным будущим типом. Можно ли уменьшить его до CompletionStage<Boolean>, используя что-то вроде flatMap в Scala, или есть другой способ сделать это?


person Caballero    schedule 30.03.2016    source источник


Ответы (1)


Да, вы ищете thenCompose(fn) операция:

Возвращает новый CompletionStage, который, когда этот этап завершается нормально, выполняется с этим этапом в качестве аргумента предоставленной функции.

Этот метод принимает в качестве параметра функцию, которая принимает результат этого этапа завершения и возвращает другой этап завершения.

Таким образом, у вас может быть следующее:

CompletionStage<String> tokenFuture = getToken();

CompletionStage<Boolean> result = tokenFuture.thenCompose(token -> {

    WSRequest request = ws.url(url).setHeader("Authorization", "Bearer " + token);

    CompletionStage<WSResponse> response = request.post(json);

    return response.thenCompose(r -> {
        if (r.getStatus() == 201) {
            return CompletableFuture.supplyAsync(() -> true);
        } else {
            return getToken().thenCompose(t -> {
                WSRequest req = ws.url(url).setHeader("Authorization", "Bearer " + t);
                return req.post(json).thenApply(b -> b.getStatus() == 201);
            });
        }
    });

});
person Tunaki    schedule 30.03.2016
comment
Следует отметить, что для платформы Play, для которой предназначен этот код, вместо этого следует использовать thenComposeAsync(), обращая внимание на правильный контекст выполнения. - person Blacklight; 18.06.2017