【问题标题】:How can I get a hold of the argument of an asynchronous callback 'onResponse'?如何获取异步回调“onResponse”的参数?
【发布时间】:2019-03-28 12:59:35
【问题描述】:

我正在使用 Apollo 的自动查询生成功能在 Java 应用程序中实现 GraphQL 客户端,到目前为止,我已经能够链接调用并且还获得了我想要的数据。问题是 Apollo 让我实现了匿名方法 ApolloCall.Callback<>(),它覆盖了 void onResponse(Response response)void onFailure(),但我无法找到一种方法来获取我想要收集的 Response 对象确保我有。

这是 Java 11 上的 Spring Boot 项目,我尝试使用 CompletableFuture,但对它以及如何使用它来解决这个特殊问题的知识有限,我觉得很不走运。我还尝试实现 Apollo 应该具有的 RxJava 支持,但我无法使用该方法解决依赖性问题。

我很确定 futures 会解决它,但我不知道怎么解决。

  public void getOwnerIdFromClient() {
    client
        .query(getOwnerDbIdQuery)
        .enqueue(
            new ApolloCall.Callback<>() {
              @Override
              public void onResponse(@Nonnull Response<Optional<GetOwnerDbIdQuery.Data>> response) {
                int ownerId =
                    response
                        .data()
                        .get()
                        .entities()
                        .get()
                        .edges()
                        .get()
                        .get(0)
                        .node()
                        .get()
                        .ownerDbId()
                        .get();

                System.out.println("OwnerId = " + ownerId);
              }

              @Override
              public void onFailure(@Nonnull ApolloException e) {
                logger.error("Could not retrieve response from GetOwnerDbIdQuery.", e);
              }
            });
  }

因为我希望在onResponse 之外使用这个int ownerId,所以这不是一个足够的解决方案。我实际上想进行此调用 x 次,并创建一个我实际获得的所有 id 的列表,因为这也可能返回一个 null id,这意味着我需要一些方法来等待它们全部完成。

【问题讨论】:

    标签: java spring asynchronous callback apollo


    【解决方案1】:

    你是对的,这可以使用 Futures 来完成:

    • 将返回类型更改为 Future
    • 在 onResponse 中完成未来

    大约:

    public Future<Integer> getOwnerIdFromClient(){
        Future<Integer> result=new CompletableFuture<Integer>();
    
        client
        .query(getOwnerDbIdQuery)
        .enqueue(
        new ApolloCall.Callback<>(){
            @Override
            public void onResponse(@Nonnull Response<Optional<GetOwnerDbIdQuery.Data>>response){
                    // get owner Id
                    System.out.println("OwnerId = "+ownerId);
                    result.complete(ownerId)
                    }
    
            @Override
            public void onFailure(@Nonnull ApolloException e){
                    logger.error("Could not retrieve response from GetOwnerDbIdQuery.",e);result.completeExceptionally(e);
    
    
                    }
            });
    
        return result;
    

    }

    【讨论】:

      【解决方案2】:

      如果其他人遇到这种情况,我花了很长时间才弄清楚泛型,但您可以使用以下方法以通用方式执行此操作(以避免复制/粘贴所有不同的查询类型)作为一个单独的类或包装器发挥作用:

          private <D extends Operation.Data, T, V extends Operation.Variables> CompletableFuture<T> execute(Query<D, T, V> query) {
          CompletableFuture<T> future = new CompletableFuture<>();
          client.query(query).enqueue(new ApolloCall.Callback<>() {
              @Override
              public void onResponse(@NotNull Response<T> response) {
                  if (response.hasErrors()) {
                      String errors = Objects.requireNonNull(response.getErrors()).stream().map(Object::toString).collect(Collectors.joining(", "));
                      future.completeExceptionally(new ApolloException(errors));
                      return;
                  }
                  future.complete(response.getData());
              }
      
              @Override
              public void onFailure(@NotNull ApolloException e) {
                  future.completeExceptionally(e);
              }
          });
      
          return future;
      }
      

      那应该只是调用的情况

      Integer myResult = execute(getOwnerDbIdQuery).get();
      

      【讨论】:

        猜你喜欢
        • 2011-09-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-12
        • 2016-05-14
        • 2011-09-27
        • 1970-01-01
        相关资源
        最近更新 更多