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);
Другие вопросы по тегам