Bạn có thể làm điều đó như thế này:
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());
}
Thay vì một CompletableFuture
chúng ta tạo ra hai, đại diện cho những con đường thực hiện khác nhau chúng ta có thể thực hiện. Các hoạt động loooooong được gửi như là runnable sau đó và sẽ cố tình hoàn thành một trong những CompletableFuture
. Các giai đoạn tiếp theo được liên kết với giai đoạn biểu thị điều kiện đã hoàn thành, sau đó cả hai đường dẫn thực hiện đều tham gia vào bước applyToEither(shortCut, Function.identity())
cuối cùng.
Tương lai shortCut
đã là loại kết quả cuối cùng và sẽ được hoàn thành với RESULT_1
, kết quả của đường dẫn đi qua null
của bạn, điều này sẽ dẫn đến việc hoàn thành toàn bộ hoạt động. Nếu bạn không thích sự phụ thuộc giữa các giai đoạn đầu tiên và giá trị kết quả thực tế của các short-cut, bạn có thể rút nó như thế này:
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());
}
Nếu bước thứ ba của bạn không phải là gương mẫu nhưng trông giống hệt như thể hiện trong câu hỏi, bạn có thể kết hợp nó với các bước con đường mã tham gia:
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);
}
sau đó chúng tôi chỉ bỏ qua bước thứ hai, someMethodThatReturnsACompletionStage
gọi, nhưng điều đó vẫn có thể đại diện cho một chuỗi dài các bước trung gian, tất cả bỏ qua mà không sự cần thiết phải tung ra một thủ thuật bỏ qua thông qua nullcheck.
Nó hoạt động, cảm ơn! Theo cùng một mẫu (tạo ra một số 'CompletableFuture' và sử dụng' applyToEither (...) ') thì có thể mở rộng nó sang một vài đường dẫn, tôi có đúng không? – Pelocho
Có, bạn có thể mở rộng nó đến nhiều đường dẫn nhưng phải cẩn thận để giữ cho mã kết quả có thể duy trì được. Có lẽ nó giúp đóng gói logic của một nhánh thành một phương thức tiện ích mà bạn có thể sử dụng nhiều lần. – Holger