我正在尝试返回一个 CompletableFuture
,它将返回来自亚马逊的响应。我的代码首先检查响应是否缓存在本地。如果是,它会返回响应,否则它会调用 Amazon。 [注意:真实版本也会缓存从亚马逊收到的响应,但我没有包含它,因为代码已经很复杂了。]
有没有办法改变我的 callAmazon
方法的实现(或以其他方式重新组织代码),这样我就不必“手动”从 amazonApi< 复制响应状态
到 finalResponse
?
我不想直接返回cacheCheck
,因为我不希望调用者能够complete()
它。
public CompletableFuture<Response> fetchProductList() {
CompletableFuture<Response> finalResponse = new CompletableFuture<>();
CompletableFuture<Response> cacheCheck = //...
// First, see if we have a cached copy
cacheCheck.whenComplete((response, throwable) -> {
if (throwable == null) {
// Cache hit. Return the cached response
finalResponse.complete(response);
} else {
// Cache miss. Call Amazon
callAmazon(finalResponse);
}
});
return finalResponse;
}
private void callAmazon(CompletableFuture<Response> finalResponse) {
CompletableFuture<Response> amazonApi = //...
amazonApi.whenComplete((response, throwable) -> {
// Copy the state to the `finalResponse`
if (throwable == null) {
finalResponse.complete(response);
} else {
finalResponse.completeExceptionally(throwable);
}
});
}
最佳答案
cacheCheck
可以抛出异常这一事实使您的要求如此复杂。
在您的情况下,我会做的是重构缓存以传递 null
(如果在缓存中未找到该值)或实际的 Response
(如果值在缓存中。
此外,我会修改 callAmazon
以直接返回 CompletableFuture
:
private CompletableFuture<Response> callAmazon() {
CompletableFuture<Response> amazonApi = //...
return amazonApi;
}
这样你就可以使用thenCompose :
final CompletableFuture<Response> cacheCheck = //...
final CompletableFuture<Response> amazonResponse = callAmazon();
final CompletableFuture<Response> finalResult =
cachedResponse.thenCompose(cacheResult -> {
return cacheResult == null ? amazonResponse : CompletableFuture.completedFuture(cacheResult);
});
如果你真的需要从缓存中抛出异常,你可以使用exceptionally将异常转换为空值,然后使用 thenCompose 来决定是使用缓存值,还是调用 Amazon:
final CompletableFuture<Response> finalResult = cachedResponse.exceptionally(e -> {
return null;
}).thenCompose(cacheResult -> {
return cacheResult == null ? amazonResponse : CompletableFuture.completedFuture(cacheResult);
});
关于java - 避免复制 CompletableFuture 的状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40728329/