次のように実行できます。
public CompletionStage<SomeResult> someMethod(SomeArgument someArgument) {
CompletableFuture<SomeResult> shortCut = new CompletableFuture<>();
CompletableFuture<ResultOfFirstOp> withChain = new CompletableFuture<>();
CompletableFuture.runAsync(() -> {
// loooooong operation
if (someCondition)
withChain.complete(validValue);
else
shortCut.complete(SomeResult.RESULT_1);
});
return withChain
.thenCompose(result -> someMethodThatReturnsACompletionStage(result))
.thenApply(result ->
result.someCondition()? SomeResult.RESULT_2: SomeResult.RESULT_3)
.applyToEither(shortCut, Function.identity());
}
1 つではなくCompletableFuture
2 つ作成し、異なる実行パスを表します。loooooong 操作は実行可能として送信され、意図的にこれらの 1 つを完了しCompletableFuture
ます。フォローアップ ステージは、満たされた条件を表すステージに連鎖され、両方の実行パスが最後のapplyToEither(shortCut, Function.identity())
ステップで結合されます。
shortCut
future はすでに最終結果の型を持っており、渡されたパスの結果である で完了します。これにより、操作全体がすぐに完了しますRESULT_1
。null
最初のステージとショートカットの実際の結果値の間の依存関係が気に入らない場合は、次のように撤回できます。
public CompletionStage<SomeResult> someMethod(SomeArgument someArgument) {
CompletableFuture<Object> shortCut = new CompletableFuture<>();
CompletableFuture<ResultOfFirstOp> withChain = new CompletableFuture<>();
CompletableFuture.runAsync(() -> {
// loooooong operation
if (someCondition)
withChain.complete(validValue);
else
shortCut.complete(null);
});
return withChain
.thenCompose(result -> someMethodThatReturnsACompletionStage(result))
.thenApply(result ->
result.someCondition()? SomeResult.RESULT_2: SomeResult.RESULT_3)
.applyToEither(shortCut.thenApply(x -> SomeResult.RESULT_1), Function.identity());
}
3 番目のステップが模範的ではなく、質問に示されているのとまったく同じように見える場合は、それをコード パスの結合ステップとマージできます。
public CompletionStage<SomeResult> someMethod(SomeArgument someArgument) {
CompletableFuture<ResultOfSecondOp> shortCut = new CompletableFuture<>();
CompletableFuture<ResultOfFirstOp> withChain = new CompletableFuture<>();
CompletableFuture.runAsync(() -> {
// loooooong operation
if (someCondition)
withChain.complete(validValue);
else
shortCut.complete(null);
});
return withChain
.thenCompose(result -> someMethodThatReturnsACompletionStage(result))
.applyToEither(shortCut, result -> result==null? SomeResult.RESULT_1:
result.someCondition()? SomeResult.RESULT_2: SomeResult.RESULT_3);
}
次に、2 番目のステップであるsomeMethodThatReturnsACompletionStage
呼び出しのみをスキップしますが、それでも中間ステップの長いチェーンを表すことができ、nullcheck による手動のスキップをロールアウトする必要なくすべてスキップされます。