Reputation: 1457
I have async method
asyncClass.getChild("test", listChild -> {
if (listChild.isOk()) {
List<String> list = listChild.isSuccess().getData()
}
return null;
});
How I can wrap this async call in CompletableFuture?
final CompletableFuture<List<String>> future = new CompletableFuture<>();
asyncClass.getChild("test", listChild -> {
if (listChild.isOk()) {
future.complete(listChild.isSuccess().getData());
}
return null;
});
return future;
Everything works fine, but I want everything to work in a separate thread calls
interface AsyncFS {
fun getChild(path: String, onResult: (Result<List<String>>) -> Unit)
}
Upvotes: 1
Views: 4606
Reputation: 20579
Change your getChild()
method to return a CompletableFuture<ListChild>
instead of taking a callback as parameter.
Without the actual code, I cannot tell exactly how this must be done, but basically the code would look like
CompletableFuture<ListChild> result = new CompletableFuture<>();
processAsynchronously(path, result);
return result;
where processAsynchronously()
performs the asynchronous computation, and at some point calls result.complete(listChild)
.
The caller will then be able to easily chain calls like
CompletableFuture<List<String>> result = asyncClass.getChild("test")
.thenAcceptAsync(listChild -> {
if (listChild.isOk()) {
return listChild.isSuccess().getData()
}
return null;
}, executor);
or any other processing using any executor he wants.
As you see, this will be much more flexible than forcing a particular type of callback.
Upvotes: 0
Reputation: 4444
Supply a Runnable or Supplier as an argument to CompletableFuture.runAsync()
or supplyAsync()
return CompletableFuture.runAsync(() -> {
doSomething();
}, optionalExecutor);
Upvotes: 0
Reputation: 45319
It seems that asyncClass.getChild
is executed asynchronously (as it takes a callback). If that's the case, then your current implementation is enough (except for the correction below).
asyncClass.getChild("test", listChild -> {
if (listChild.isOk()) {
future.complete(listChild.isSuccess().getData());
} else {
future.complete(null); //you need to do this
//or future.completeExceptionally(exception) if this is a failure
}
});
If you want getChild
to run in a separate thread, then I'd strongly suggest you redesign the method to make it return List<String>
instead of taking a callback. This design makes it awkward to run getChild
asynchronously.
interface AsyncFS {
fun getChild(path: String): List<String> //don't trust my syntax
}
And then run it asynchronously in this way:
CompletableFuture<List<String>> future =
CompletableFuture.supplyAsync(() -> asyncClass.getChild("test"));
return future;
Upvotes: 3