我的异步调用做错了什么?
What am i doing wrong with my async call?
我有这段代码:
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的新手,我想做以下事情:
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);
}
或者类似的东西,它让代码变得可怕,当我想在之后做更多的异步请求时,我这里有一个回调地狱,有什么办法可以避免它吗?我在这里有什么选择?
我认为你混淆了 asnychronous 和 synchronous.
如果你
want to do async call to get and extract a list of stocks, only after the request completed I want to do the next things in the main method
那么你实际上想要执行一个同步调用。
一个异步调用将执行请求,然后做其他事情(与请求无关),在将来的某个时候你会得到请求的结果并处理它。
要执行 同步 调用,这可能是您想要的,请尝试像这样调整您的代码:
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
。将以下代码段作为不处理不成功调用的起点。
private static CompletableFuture<ArrayList<Stock>> getAllAvailableStocks(String url) {
CompletableFuture<ArrayList<Stock>> result = new CompletableFuture<>();
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");
ArrayList<Stock> stocks = new ArrayList<Stock>();
if (response != null && response.getStatus() == 200) {
JsonNode body = response.getBody();
// TODO Parse body and add items to `stocks`
}
result.complete(stocks);
}
public void cancelled() {
System.out.println("The request has been cancelled");
}
});
return result;
}
可以使用的方法如下:
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
我有这段代码:
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的新手,我想做以下事情:
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);
}
或者类似的东西,它让代码变得可怕,当我想在之后做更多的异步请求时,我这里有一个回调地狱,有什么办法可以避免它吗?我在这里有什么选择?
我认为你混淆了 asnychronous 和 synchronous.
如果你
want to do async call to get and extract a list of stocks, only after the request completed I want to do the next things in the main method
那么你实际上想要执行一个同步调用。
一个异步调用将执行请求,然后做其他事情(与请求无关),在将来的某个时候你会得到请求的结果并处理它。
要执行 同步 调用,这可能是您想要的,请尝试像这样调整您的代码:
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
。将以下代码段作为不处理不成功调用的起点。
private static CompletableFuture<ArrayList<Stock>> getAllAvailableStocks(String url) {
CompletableFuture<ArrayList<Stock>> result = new CompletableFuture<>();
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");
ArrayList<Stock> stocks = new ArrayList<Stock>();
if (response != null && response.getStatus() == 200) {
JsonNode body = response.getBody();
// TODO Parse body and add items to `stocks`
}
result.complete(stocks);
}
public void cancelled() {
System.out.println("The request has been cancelled");
}
});
return result;
}
可以使用的方法如下:
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