Дождитесь завершения асинхронного обратного вызова и передайте значение - PullRequest
0 голосов
/ 05 июня 2018

У меня есть следующий фрагмент кода:

private ValContainer<CompletableFuture<String>> valContainer = new ValContainer<>();

public void fetchAsync(final String attrName) {

        QueryAsyncCallback asyncCallback = new QueryAsyncCallback() {
            @Override
            public void onSuccess(Message response) {
                final Data value = response.results().get("value");
                String text = value.toString();
                CompletableFuture<String> result = CompletableFuture.completedFuture(text);
                valContainer.setVal(result);
            }

            @Override
            public void onError(CallbackError error) {
                LOG.info("Error occurred");
            }

            @Override
            public void onTimeout() {
                LOG.info("Timeout occurred");
            }
        };

        Message request = new Messsage("com.example.val", "local", 0, "fetch");
        request.parameters().put("name", attrName);

        MsgOptions options = new MsgOptions(5000);
        try {
            queue.query(request, options, asyncCallback);
        } catch (QueueAccessException e) {
            e.printStackTrace();
        }
    }

Прямо сейчас я могу легко получить значения, по которым я сделал запрос в onSuccess() обратном вызове.ValContainer - это просто общий контейнер, так что я могу сохранить значения внутри анонимного класса.К сожалению, в функции Main я пытаюсь получить доступ к этому valContainer, но, к сожалению, так как это асинхронный запрос, я получаю NullPointerException.

...
((JavaServiceImpl) javaService).fetchAsync("test");
System.out.println("inMain value: " + ((JavaServiceImpl) javaService).getValContainer().getVal().get()); <-- this is going to be NullPointerException
...

Затем через 100 мс я получаю значение в методе onSuccess().Здесь в основном выполнения Thread.sleep(100) было бы достаточно, чтобы получить значение, которое я надеюсь получить, но я действительно не хочу блокировать поток.Есть ли способ сделать это аккуратно?

1 Ответ

0 голосов
/ 05 июня 2018

Не оставляйте val без инициализации в ValContainer.Инициализируйте его как new CompletableFuture<>().

private ValContainer<CompletableFuture<String>> valContainer = new ValContainer<>(new CompletableFuture<>());


public class ValContainer<T> {
    T val;

    public ValContainer(T val) {
        this.val = val;
    }
}

Затем измените свой метод onSuccess на

String text = value.toString(); 
valContainer.getVal().complete(text);

Вам не нужно создавать метод CompletableFuture in onSuccess.

Сэто, [..]getValContainer().getVal().get() блокирует, пока будущее не будет завершено.

...