Reputation: 6733
I have an async function in java. I want to make async calls to a number of APIs (in parallel) then create a response. Since I need the different results, I though to save them in the class. I have helper functions to make the calls to the external APIs (classes with a call function which return CompletableFuture<List<T>>
). I can do this like this:
public class MyAction{
private List<Bar> bars;
private List<Baz> bazs;
public CompletableFuture<Foo> run() {
CompletableFuture<Void> fetchBars = new BarFetcher().call().thenAccept(this::populateBars);
CompletableFuture<Void> fetchBazs = new BazFetcher().call().thenAccept(this::populateBazs);
return CompletableFuture.allOf(fetchBars, fetchBazs).thenApply(this::getFoo);
}
private void populateBars(final List<Bar> bars) {
this.bars = bars;
}
private void populateBaz(final List<Baz> bazs) {
this.bazs = bazs;
}
private Foo getFoo(final Void dummy) {
return new Foo(bars, bazs);
}
}
But I had to add an unnecessary parameter (final Void dummy
) to the getFoo
function to make it work. Can I avoid this? if should really just be getFoo()
not getFoo(final Void dummy)
. Is there any way to wait for multiple futures to complete and then chain in another function without passing it directly any data?
Note: The example only has two initial calls to fetch data (fetchbars
and fetchBazs
) before the final processing (getFoo
). However, I actually will have more than two. I currently have three, but it may grow by one or two more. I would like to run all the initial calls in parallel, then the final processing once all have completed.
Upvotes: 2
Views: 1112
Reputation: 298233
Use the right tool for the job. To combine two futures, just use
public CompletableFuture<Foo> run() {
return new BarFetcher().call().thenCombine(new BazFetcher().call(),
(List<Bar> bars, List<Baz> bazs) -> new Foo(bars, bazs));
}
or even simpler
public CompletableFuture<Foo> run() {
return new BarFetcher().call().thenCombine(new BazFetcher().call(), Foo::new);
}
Upvotes: 3
Reputation: 56433
you could change the use of method reference to a lambda as follows:
return CompletableFuture.allOf(fetchBars, fetchBazs)
.thenApply(e -> getFoo());
then you don't have to introduce a dummy parameter.
Note, I am not that familiar with the CompletableFuture
API so, there may be more suitable solutions out there.
Upvotes: 0