如何在方法中保存 Vert.x WebClient 结果和 return

How to save Vert.x WebClient result and return it in method

我的 Java Vert.x 项目中使用了一个方法,它使用 WebClient 调用另一个服务。我想将该调用的结果保存在 JsonObject 和 return 中。我假设我需要为此使用期货,但是当我 运行 GetItemsService.retrieveItems 时,除了我的 "print future below" 消息外,我在控制台中看到的是 Future{unresolved}.

如何将 GetItemsManager.getItems 网络客户端调用的结果保存在变量中?

public class GetItemsManager {
    public Future<JsonObject> getItems(Future<JsonObject> future, Vertx vertx, RoutingContext routingContext) {
        WebClient webClient = WebClient.create(vertx);
        HttpServerResponse response = routingContext.response();
        JsonObject data = new JsonObject();
        response.setChunked(true);
        response.putHeader("content-type", "text/plain");
        response.putHeader("Access-Control-Allow-Origin", "*");
        webClient.post(80, Constants.API_URL, "/items")
            .as(BodyCodec.jsonArray())
            .putHeader("Accept", "application/json")
            .putHeader("Content-Type", "application/json")
            .putHeader("ugws7", Constants.SERVICES_URL)
            .sendJsonObject(new JsonObject().put("mutator", "*"), ar -> {
                if (ar.succeeded()) {
                    HttpResponse<JsonArray> result = ar.result();
                    JsonArray body = result.body();
                    data.put("data", body.getJsonObject(0));
                    future.complete(data);
                } else {
                    future.fail(new JsonObject().put("error", ar.cause().getMessage()).encode());
                }
            });
            return future;
    }
}

public class GetItemsService {
    public void retrieveItems(Vertx vertx, RoutingContext routingContext) {
        Future<JsonObject> future = Future.future();
        new GetItemsManager().getItems(future, vertx, routingContext);
        String jsonObject = future.toString();
        System.out.println("print future below");
        System.out.println(jsonObject);
    }
}

更新

根据 Peter 的回答,我尝试使用以下内容更新我的代码:

   public class GetItemsService {
    public void retrieveItems(Vertx vertx, RoutingContext routingContext) {
        Future<JsonObject> future = Future.future();
        new GeItemsManager().getItems(future, vertx, routingContext);
        String jsonObject;
        Future<JsonObject> f = future.setHandler(handler -> {
            handler.result();
        });
        System.out.println("Print future below");
        System.out.println(f);
    }
  }

我仍然无法将调用结果分配给变量 (f)。

试试

public class GetItemsService {
    public void retrieveItems(Vertx vertx, RoutingContext routingContext) {
        Future<JsonObject> future = Future.future();
        new GetLocationsManager().getItems(future, vertx, routingContext);
        future.setHandler(h ->{
            routingContext.response().end(h.result().encode());
        });
    }
}

我希望这有助于我尝试向您的代码添加有用的注释。

GetItemsManager

public class GetItemsManager {
public Future<JsonObject> getItems(Vertx vertx, RoutingContext routingContext) {
    //Note1: you can create the future here, no need to pass as a parameter
    Future<JsonObject> future = Future.future(); 
    ...
    webClient.post(80, Constants.API_URL, "/items")
        ...
        .sendJsonObject(new JsonObject().put("mutator", "*"), ar -> {
            if (ar.succeeded()) {
                ...
                future.complete(data);
            } else {
                future.fail(new JsonObject().put("error", ar.cause().getMessage()).encode());
            }
        });
        return future;
}
}

GetItemsService

public class GetItemsService {
    public void retrieveItems(Vertx vertx, RoutingContext routingContext) {
        new GetLocationsManager().getItems(vertx, routingContext) // returns Future<JsonObject>
            .setHandler(handler -> {
                //Note2: this codeblock is executed when your future is completed (or failed)
                if(handler.succeeded()){
                    //Note3: handler.result() contains the result from the getItems call (future.complete(data))
                    JsonObject items = handler.result();
                    doSomethingWithTheItems(items);
                    String itemsEncodedToString = items.encode();
                    // serve the response
                    routingContext.response().end(itemsEncodedToString);
                }else{
                    // serve error response
                    routingContext.response().end("something terrible happened" + handler.cause());
                }
        });
    }

    public void doSomethingWithTheItems(JsonObject items){
        // do something here with your items
    }
}

// 如果你想执行一些其他的异步方法,选项 2

public class GetItemsService {
    public void retrieveItems(Vertx vertx, RoutingContext routingContext) {
        new GetLocationsManager().getItems(vertx, routingContext);
            .compose(this::doSomethingAsyncWithTheItems)
            .setHandler(handler -> {
                if(handler.succeeded()){
                    //Note4: handler.result() contains the result from the doSomethingAsyncWithTheItems call (future.complete(...))
                    JsonObject didSomethingWithTheItems = handler.result();
                    routingContext.response().end(didSomethingWithTheItems.encode());
                }else{
                    // serve error response
                    routingContext.response().end("something terrible happened");
                }
        });
    }

    public Future<JsonObject> doSomethingAsyncWithTheItems(JsonObject items){
        Future<JsonObject> future = Future.future(); 
        otherAsyncCallThatReturnsAFuture.setHandler(handler -> {
            if(handler.succeeded()){
                future.complete(...)
            }else{
                future.fail(...)
            }
        })
        return future;
    }
}