Java 我的异步调用有什么问题?

Java 我的异步调用有什么问题?,java,asynchronous,callback,asynccallback,Java,Asynchronous,Callback,Asynccallback,我有一段代码: public static void main(String[] args) throws UnirestException { ArrayList<Stock> listStock = getAllAvailableStocks("https://api.iextrading.com/1.0/ref-data/symbols"); //doing more actions after the one before, usi

我有一段代码:

public static void main(String[] args) throws UnirestException {
    ArrayList<Stock> listStock 
             = getAllAvailableStocks("https://api.iextrading.com/1.0/ref-data/symbols");
    //doing more actions after the one before, using the data from the listStock etc.
}


private static ArrayList<Stock> getAllAvailableStocks(String url) {
    ArrayList<Stock> stocks = new ArrayList<Stock>();
    Future<HttpResponse<JsonNode>> future = Unirest.get(url)
              .header("accept", "application/json")
              .asJsonAsync(new Callback<JsonNode>() {
                public void failed(UnirestException e) {
                    System.out.println("The request has failed");
                }

                public void completed(HttpResponse<JsonNode> response) {
                     ObjectMapper objectMapper = new ObjectMapper();
                    try {
                        listStock = objectMapper.readValue(response.getRawBody(), new TypeReference<List<Stock>>(){});
                    } catch (Exception e) {
                        System.out.println("all is fucked");
                    }   
                    return listStock;
                }

                public void cancelled() {
                    System.out.println("The request has been cancelled");
                }

            });
}
我是java的新手,我想做以下工作:

getAllAvailableStocks("https://api.iextrading.com/1.0/ref-data/symbols",new Callback<JsonNode>() {
            public void failed(UnirestException e) {
                System.out.println("The request has failed");
            }

        public void completed(HttpResponse<JsonNode> response) {
             ArrayList<Stock> listStock = new ArrayList<Stock>();
             ObjectMapper objectMapper = new ObjectMapper();
             int code = response.getStatus();
             System.out.println(code);
            try {
                listStock = objectMapper.readValue(response.getRawBody(), new TypeReference<List<Stock>>(){});
            } catch (Exception e) {

            }   
            System.out.println(listStock);
        }

        public void cancelled() {
            System.out.println("The request has been cancelled");
        }

    });
}



private static Future<HttpResponse<JsonNode>> getAllAvailableStocks(String url,Callback<JsonNode> cb) {
    return Unirest.get(url)
              .header("accept", "application/json")
              .asJsonAsync(cb);
}
1我想进行异步调用以获取并提取股票列表,只有在请求完成后,我才想在main方法中执行下一步操作

2如何从我构建的方法中提取数据,以便在方法之外使用数据

3如果我需要执行以下操作:

getAllAvailableStocks("https://api.iextrading.com/1.0/ref-data/symbols",new Callback<JsonNode>() {
            public void failed(UnirestException e) {
                System.out.println("The request has failed");
            }

        public void completed(HttpResponse<JsonNode> response) {
             ArrayList<Stock> listStock = new ArrayList<Stock>();
             ObjectMapper objectMapper = new ObjectMapper();
             int code = response.getStatus();
             System.out.println(code);
            try {
                listStock = objectMapper.readValue(response.getRawBody(), new TypeReference<List<Stock>>(){});
            } catch (Exception e) {

            }   
            System.out.println(listStock);
        }

        public void cancelled() {
            System.out.println("The request has been cancelled");
        }

    });
}



private static Future<HttpResponse<JsonNode>> getAllAvailableStocks(String url,Callback<JsonNode> cb) {
    return Unirest.get(url)
              .header("accept", "application/json")
              .asJsonAsync(cb);
}

或者诸如此类的东西,它使代码变得可怕,当我想在之后执行更多的异步请求时,我这里有一个回调地狱,有没有办法避免它?我在这里有什么选择?

我认为你把时间和同步混淆了

如果你

想要做异步调用来获取并提取股票列表,只有在请求完成后我才想在main方法中做下一件事

然后您实际上想要执行同步调用

异步调用是执行请求,然后执行与请求无关的其他操作,然后在将来的某个时候获得请求的结果并处理它

要执行同步调用(这可能是您想要的),请尝试如下调整代码:

private static ArrayList<Stock> getAllAvailableStocks(String url) {
    ArrayList<Stock> stocks = new ArrayList<Stock>();
    Future<HttpResponse<JsonNode>> future = Unirest.get(url)
              .header("accept", "application/json")
              .asJsonAsync(new Callback<JsonNode>() {
                public void failed(UnirestException e) {
                    System.out.println("The request has failed");
                }

                public void completed(HttpResponse<JsonNode> response) {
                    System.out.println("The request succeeded");
                }

                public void cancelled() {
                    System.out.println("The request has been cancelled");
                }
            });

    HttpResponse<JsonNode> response = future.get(); // NOTE: This call is blocking until the request is finished
    if (response != null && response.getStatus() == 200) {
        JsonNode body = response.getBody();
        // TODO Parse body and add items to `stocks`
    }
    return stocks;
}
ArrayList<Stock> stocks = getAllAvailableStocks(...);
stocks.forEach(x -> System.out.println(x));
该方法可按如下方式使用:

CompletableFuture<ArrayList<Stock>> stocksFuture = getAllAvailableStocks(...);
stocksFuture.thenAccept((stocks) -> {
    // NOTE: This will be called after and only if the request succeeded
    stocks.forEach(x -> System.out.println(x));
});

System.out.println("This is probably executed before the above request finished.");

Thread.sleep(10000); // If you are calling from your `main` method: Prevent JVM exit

在填充listStock之后,您需要从完成的块中调用下一段逻辑。以静态方法编写所有内容是非常罕见的,因此我认为您可能是java的真正新手-如果是这样,我建议您在开始研究未来和异步之前,先深入了解基本java,如果不是,我道歉。我不同意。OP需要一个异步管道-在调用完成后做一些事情就像使用CompletableFuture并添加thenApply调用一样简单。Boris你能给我看看你正在谈论的示例吗?@BoristheSpider谢谢你指出这一点。我已经添加了一个相应的例子。你的异步代码是相当破碎的-你忽略失败可以取消,所以一旦失败你的可完成的未来将永远不会完成。。。