似乎是一个常见问题,但我不确定解决方案。

我在Java上使用Vert.x来调用另一个服务。我正在使用Vert.x的WebClient库。当我发出POST请求时,其中一个参数是匿名函数。如果请求成功,那么我得到我的数据。

问题是在我的其余方法中,这些数据是从匿名函数之外获取的。我希望我的方法返回从我的匿名函数获得的数据。数据在body变量中。

private JsonArray itemTypes() {
  WebClient webClient = WebClient.create(vertx);
  webCLient.post(80, "myApi.com", "/api/items")
    .sendJsonObject(new JsonObject().put("mutator", "*"), ar -> {
      if (ar.succeeded) {
        HttpResponse<JsonArray> result = ar.result();
        JsonArray body = result.body();
      } else {
        System.out.println(ar.cause().getMessage());
      }
    });
}


现在,如果我尝试在匿名函数之外声明body变量并将其分配到内部(以便我可以返回该值),则我的IDE会抱怨Local variable body defined in an enclosing scope must be final or effectively final

我本质上想做这样的事情:

private JsonArray itemTypes() {
  JsonArray body;
  WebClient webClient = WebClient.create(vertx);
  webCLient.post(80, "myApi.com", "/api/items")
    .sendJsonObject(new JsonObject().put("mutator", "*"), ar -> {
      if (ar.succeeded) {
        HttpResponse<JsonArray> result = ar.result();
        body = result.body();
      } else {
        System.out.println(ar.cause().getMessage());
        body = new JsonArray();
      }
    });
  return body;
}


我试过将JsonArray主体变量定为final,但这不起作用。我也尝试将整个webClient.post(....)调用分配给一个变量,但这也不起作用。

如何在匿名函数之外访问body数据,以便可以在我的方法中返回它?

最佳答案

您遇到的问题是WebClient似乎是完全异步的。这意味着当您调用.sendJsonObject时,它基本上发送请求并立即返回; WebClient等待答案时,您的代码将继续运行。

收到响应后,它可能会在其他线程中调用您提供的回调lambda。这可能会在几秒钟后发生,与此同时许多其他代码可能已经有时间运行。

您需要的是让您的主代码等待收到响应。这可以通过多种方式完成,其中一种方式是创建CompletableFuture<T>,让回调调用.complete(theValue)方法,然后让外部代码调用.get()等待并接收值。

换句话说,外部代码将定义并等待CompletableFuture<T>完成,然后让.sendJsonObject回调为您提供所需的值。

10-04 18:59