簡體   English   中英

Java CompletableFuture:避免回調地獄

[英]Java CompletableFuture: Avoid callback hell

我對Java中的CompletableFuture有疑問。 我正在等待CompletableFuture完成,並且根據收到的結果,我想要調用一個新任務並等待CompletableFuture完成或做一些不同的事情。 我對我的解決方案不滿意,因為有很多回調,並且閱讀不同。 你能幫助我改進我的代碼嗎?

final CompletableFuture<String> future = new CompletableFuture<>();

final ActorRef processCheckActor = actorSystem.actorOf(
    springExtension.props("ProcessCheckActor"), "processCheckActor-" + new Random().nextInt());

final CompletableFuture<Object> checkResponse =
    PatternsCS.ask(processCheckActor, new ProcessToCheckMessage(processId), TIMEOUT)
        .toCompletableFuture();

checkResponse.thenAccept(obj -> {
  final ProcessCheckResponseMessage msg = (ProcessCheckResponseMessage) obj;
  if (msg.isCorrect()) {
    final CompletableFuture<Object> response =
        PatternsCS.ask(processSupervisorActor, new ProcessStartMessage(processId), TIMEOUT)
            .toCompletableFuture();

    response.thenAccept(obj2 -> {
      future.complete("yes");
    });
  } else {
    future.complete("no");
  }
});

首先,您應該避免創建CompletableFuture<Object> 泛型類型應該是函數返回的類型(在您的情況下為CompletableFuture<ProcessCheckResponseMessage> )。 這樣你就不需要演員了。

我建議使用thenApply而不是thenAccept 這將為您創建第二個CompletableFuture,這意味着您不再需要第一行中的聲明。

最后,作為一般規則,你應該三思而后行多線lambda,並且絕對避免使用嵌套的lambdas。 您應該考慮為這些lambda創建一個新方法。

我的2美分示例代碼可以幫助您回調場景。

我編寫了3個函數: testFunctiongetResponseMessagegetResponseString

  • testFunction是主要功能。
  • getResponseMessage通過thenApply鏈接到主testFunction
  • getResponseString最后通過thenCompose

訣竅是通過高階函數鏈接多個較小的函數,如thenApplythenComposethenCombine等。

public CompletableFuture<String> testFunction() {

    Future<Object> fut = Patterns.ask(getContext().actorSelection("actor1"), new ProcessToCheckMessage(1), 10);

    return FutureConverters.toJava(fut).toCompletableFuture()

            .thenApply(obj -> getResponseMessage(obj))

            .thenCompose(processCheckResponseMessage -> getResponseString(processCheckResponseMessage));
}

public ProcessCheckResponseMessage getResponseMessage(Object obj) {
    if (obj instanceof ProcessCheckResponseMessage) {
        return (ProcessCheckResponseMessage) obj;
    } else {
        throw new RuntimeException("unexpected data");
    }
}

public CompletableFuture<String> getResponseString(ProcessCheckResponseMessage processCheckResponseMessage) {
    if (processCheckResponseMessage.isCorrect()) {
        Future<Object> rest = Patterns.ask(getContext().actorSelection("actor2"), new ProcessStartMessage(1), 10);
        return FutureConverters.toJava(rest).toCompletableFuture().thenApply(obj -> "yes");
    } else {
        return CompletableFuture.completedFuture("no");
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM