CompletableFuture обертка
У меня есть асинхронный метод
asyncClass.getChild("test", listChild -> {
if (listChild.isOk()) {
List<String> list = listChild.isSuccess().getData()
}
return null;
});
Как я могу обернуть этот асинхронный вызов в CompletableFuture?
final CompletableFuture<List<String>> future = new CompletableFuture<>();
asyncClass.getChild("test", listChild -> {
if (listChild.isOk()) {
future.complete(listChild.isSuccess().getData());
}
return null;
});
return future;
Все отлично работает, но я хочу, чтобы все работало в отдельном потоке вызовов
interface AsyncFS {
fun getChild(path: String, onResult: (Result<List<String>>) -> Unit)
}
3 ответа
Кажется, что asyncClass.getChild
выполняется асинхронно (так как требуется обратный вызов). Если это так, то вашей текущей реализации достаточно (за исключением исправления ниже).
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
}
});
Если ты хочешь getChild
чтобы запустить в отдельном потоке, то я настоятельно рекомендую вам изменить метод, чтобы он вернулся List<String>
вместо того, чтобы принять обратный звонок. Этот дизайн делает его неудобным для запуска getChild
асинхронно.
interface AsyncFS {
fun getChild(path: String): List<String> //don't trust my syntax
}
А затем запустите его асинхронно следующим образом:
CompletableFuture<List<String>> future =
CompletableFuture.supplyAsync(() -> asyncClass.getChild("test"));
return future;
Измени свой getChild()
способ вернуть CompletableFuture<ListChild>
вместо того, чтобы принимать обратный вызов в качестве параметра.
Без реального кода я не могу точно сказать, как это должно быть сделано, но в основном код будет выглядеть
CompletableFuture<ListChild> result = new CompletableFuture<>();
processAsynchronously(path, result);
return result;
где processAsynchronously()
выполняет асинхронные вычисления и в какой-то момент вызывает result.complete(listChild)
,
После этого вызывающий абонент сможет легко связывать вызовы, такие как
CompletableFuture<List<String>> result = asyncClass.getChild("test")
.thenAcceptAsync(listChild -> {
if (listChild.isOk()) {
return listChild.isSuccess().getData()
}
return null;
}, executor);
или любая другая обработка с использованием любого исполнителя, которого он хочет.
Как видите, это будет гораздо более гибким, чем принудительный вызов определенного типа.
Поставьте Runnable или Поставщика в качестве аргумента CompletableFuture.runAsync()
или же supplyAsync()
return CompletableFuture.runAsync(() -> {
doSomething();
}, optionalExecutor);