2016-11-19 8 views
1

Java에서 CompletableFuture와 관련된 질문이 있습니다. CompletableFuture가 완료 될 때까지 기다리는 중이고받은 결과에 따라 새 작업을 호출하고 CompletableFuture가 완료되거나 다른 작업을 수행하기를 기다리고 싶습니다. 콜백이 너무 많아서 읽는 방법이 다르므로 내 솔루션에 만족하지 않습니다. 제 코드 개선에 도움을 줄 수 있습니까?Java CompletableFuture : 콜백 hell 피하기

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

답변

2

우선 CompletableFuture<Object>을 작성하지 않아야합니다. 제네릭 형식은 함수가 반환하는 형식이어야합니다 (CompletableFuture<ProcessCheckResponseMessage>). 그렇게하면 캐스팅이 필요하지 않습니다.

thenAccept 대신 thenApply을 사용하는 것이 좋습니다. 이렇게하면 두 번째 CompletableFuture가 만들어 지므로 첫 번째 줄에 선언이 더 이상 필요하지 않습니다.

마지막으로 일반적으로 여러 줄 람다에 대해 두 번 생각하고 중첩 된 람다를 피하십시오. 대신에 이러한 람다에 대한 새로운 방법을 만드는 것을 고려해야합니다.

1

콜백 시나리오에 도움이되는 샘플 코드가 2 센트입니다.

나는 3 가지 기능을 작성했습니다 : testFunction, getResponseMessagegetResponseString.

  • testFunction이 주 기능입니다.
  • getResponseMessage
  • thenApply
  • getResponseString 통해 메인 testFunction 체인이된다 thenCompose 내지 끝에 체인화된다.

트릭 thenApply 같은 고차 함수 thenCompose 통해 체인 작은 여러 기능이다 thenCombine

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