I have the following code with several asynchronous calls depending on each other (calls can be apis REST, for example) and in the end process all the results. This is my sample code:
private void foo1(String uuid, Handler<AsyncResult<JsonObject>> aHandler) {
//call json api, for example
JsonObject foo1 = new JsonObject();
foo1.put("uuid", "foo1");
aHandler.handle(Future.succeededFuture(foo1));
}
private void foo2(String uuid, Handler<AsyncResult<JsonObject>> aHandler) {
//call json api, for example
JsonObject foo2 = new JsonObject();
foo2.put("uuid", "foo2");
aHandler.handle(Future.succeededFuture(foo2));
}
private void foo3(String uuid, Handler<AsyncResult<JsonObject>> aHandler) {
//call json api, for example
JsonObject foo3 = new JsonObject();
foo3.put("uuid", "foo3");
aHandler.handle(Future.succeededFuture(foo3));
}
private void doSomething(JsonObject result1, JsonObject result2, JsonObject result3, Handler<AsyncResult<JsonObject>> aHandler) {
JsonObject finalResult =new JsonObject();
aHandler.handle(Future.succeededFuture(finalResult));
}
private void processToRefactor (String uuid, Handler<AsyncResult<JsonObject>> aHandler) {
foo1(uuid, ar -> {
if (ar.succeeded()) {
JsonObject foo1 = ar.result();
foo2(foo1.getString("uuid"), ar2 ->{
if (ar2.succeeded()) {
JsonObject foo2 = ar2.result();
foo3(foo2.getString("uuid"), ar3 -> {
if (ar3.succeeded()) {
JsonObject foo3 = ar3.result();
doSomething(foo1, foo2, foo3, aHandler);
} else {
ar3.cause().printStackTrace();
}
});
} else {
ar2.cause().printStackTrace();
}
});
} else {
ar.cause().printStackTrace();
}
});
}
In the previous code I have all the results available to use in the "doSomething" method if all the calls have been successful. I have tried to refactor this code using the simple "HelloWord" example from the following link https://streamdata.io/blog/vert-x-and-the-async-calls-chain/
This is my result:
private void process(String uuid, Handler<AsyncResult<JsonObject>> aHandler) {
Future<JsonObject> future = Future.future();
future.setHandler(aHandler);
Future<JsonObject> futureFoo1 = Future.future();
foo1(uuid, futureFoo1);
futureFoo1.compose(resultFoo1 -> {
Future<JsonObject> futureFoo2 = Future.future();
foo2(resultFoo1.getString("uuid"), futureFoo2);
return futureFoo2;
}).compose(resultFoo2 ->{
Future<JsonObject> futureFoo3 = Future.future();
foo3(resultFoo2.getString("uuid"), futureFoo3);
return futureFoo3;
}).compose(resultFoo3 -> {
// How to get result1, result2 and result3?
// doSomething(resultFoo1, resultFoo2, resultFoo3, aHandler);
}, future);
}
The new code is cleaner and clearer but when using compose, at the moment of calling the function "doSomething" I do not have all the results of the calls available. How do I get all the results at the end of the chain?
On the other hand, how do you do if one of the apis call methods returns an array? That is to say, for each element of the array, a chain of functions is applied, independently of the fact that some have results and others do not. For example:
private void foo1Array(String uuid, Handler<AsyncResult<JsonArray>> aHandler) {
//call json api that return array, for example
JsonArray result = new JsonArray();
JsonObject foo1 = new JsonObject();
foo1.put("uuid", "foo1");
JsonObject foo2 = new JsonObject();
foo1.put("uuid", "foo2");
JsonObject foo3 = new JsonObject();
foo1.put("uuid", "foo3");
result.add(foo1);
result.add(foo2);
result.add(foo3);
aHandler.handle(Future.succeededFuture(result));
}
private void processArray(String uuid, Handler<AsyncResult<JsonObject>> aHandler) {
Future<JsonObject> future = Future.future();
future.setHandler(aHandler);
Future<JsonArray> futureFoo1 = Future.future();
foo1Array(uuid, futureFoo1);
futureFoo1.compose(resultArray -> {
List<Future> futures = new ArrayList<Future>();
for (int i = 0; i < resultArray.size(); i ++) {
JsonObject resultFoo1 = resultArray.getJsonObject(i);
Future<JsonObject> futureFoo2 = Future.future();
foo2(resultFoo1.getString("uuid"), aHandler);
futures.add(futureFoo2);
}
CompositeFuture.any(futures).setHandler(ar -> {
//What to do here?
});
}, future);
}
How to call functions foo2, foo3, ... with the result of foo1Array and then use it in doSomething?