简体   繁体   English

用另一个 CompletableFuture 结果完成 CompletableFuture

[英]Complete CompletableFuture with another CompletableFuture result

I'm doing async http call such way我正在做异步 http 这样的调用

public CompletableFuture<String> doPost(String path, String json) {
        CompletableFuture<String> result = new CompletableFuture<>();
        Request request = new Request.Builder().url(this.address + path).post(RequestBody.create(json, JSON)).build();
        httpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                result.completeExceptionally(new TerminationException());
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                result.complete(response.body().string());
            }
        });
    }

But it is possible that response will have one of the codes that I'll need to retry and the code should be但是响应可能会包含我需要重试的代码之一,并且代码应该是

@Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                if (!retries.contains(responce.code()) {
                    result.complete(response.body().string());
                } else {
                    // Do retry here
                }
            }

In retry I want to call doPost recursively and use it's return value as a result of initial call.在重试中,我想递归调用 doPost 并使用它的返回值作为初始调用的结果。 So it returns some completable future, how complete initial CF with it's result in async way (without doint.get())?所以它返回了一些完整的未来,如何以异步方式完成初始 CF(没有 doint.get())?

Thanks.谢谢。

You can use delegation, eg您可以使用委托,例如

public CompletableFuture<String> doPost(String path, String json) {
    CompletableFuture<String> result = new CompletableFuture<>();
    doPostImpl(this.address + path, json, result, 10);
    return result;
}

private void doPostImpl(
    String url, String json, CompletableFuture<String> result, int maxRetries) {

    Request request = new Request.Builder()
        .url(url).post(RequestBody.create(json, JSON)).build();

    httpClient.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(@NotNull Call call, @NotNull IOException e) {
            result.completeExceptionally(new TerminationException());
        }

        @Override
        public void onResponse(
            @NotNull Call call, @NotNull Response response) throws IOException {

            if(maxRetries <= 0 || !retries.contains(response.code())) {
                result.complete(response.body().string());
            } else {
                doPostImpl(url, json, result, maxRetries - 1);
            }
        }
    });
}

The front-end method delegates to a method receiving the target future.前端方法委托给接收目标未来的方法。 When retrying, the implementation method is invoked again with the same future.重试时,以相同的未来再次调用实现方法。 Therefore, there is no need to transfer results from one future to another.因此,没有必要将结果从一个未来转移到另一个未来。


Taking the question literally, you can transfer the result of a future to another using从字面上理解这个问题,您可以将未来的结果转移到另一个使用

future2.whenComplete((value,throwable) -> {
    if(throwable != null) future1.completeExceptionally(throwable);
    else future1.complete(value);
});

but this could create a dependency chain as long as the number of retries.但这可能会创建一个依赖链,只要重试次数。 As shown above, there is no need for that.如上所示,没有必要这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM