[英]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個函數: testFunction
, getResponseMessage
和getResponseString
。
testFunction
是主要功能。 getResponseMessage
通過thenApply
鏈接到主testFunction
getResponseString
最后通過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");
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.