简体   繁体   English

Vertx中的异步性,列表在设置之前返回空

[英]Asynchronicity in Vertx, list returns empty before it is set

In my MainVerticle I set the router 在我的MainVerticle中,设置路由器

router.get("/persons").handler(ctx -> apiService.getPersons(ctx, client));

I want to call the same host twice, first I need to get a list of person ids and then call another method of the same host to get the person details. 我想两次调用同一主机,首先我需要获取人员ID列表,然后调用同一主机的另一种方法以获取人员详细信息。 . So, in this code, I am doing a get call in another one. 因此,在这段代码中,我正在另一个代码中进行get调用。 Because of asynchronicity, the personList is empty since Vertx does not wait the reply of the second call, the reply of the second call comes later but of course the personList is empty. 由于异步性,由于Vertx不等待第二个呼叫的答复,所以personList为空,第二个呼叫的答复稍后出现,但是personList当然为空。 In my test case, the iterator has two elements. 在我的测试案例中,迭代器有两个元素。 How should I implement it in order to be sure that the list will be returned well set? 我应该如何实现它,以确保可以正确返回列表?

        public void getPersons(RoutingContext routingContext, WebClient client){
    logger.info("getpersons");
    routingContext.response().headers().add("content-type", "application/json");
    String wshost= ConfigUtils.getStringConfig(vertx,"personws.url");
    String url = wshost+"/persons";
    client.getAbs(url).send(response -> {
        try {
            if (response.succeeded() && response.result().statusCode()==200) {
                List<Person> personList = new ArrayList<Person>();
                logger.info("Server content " + response.result().bodyAsString());

                Iterator<Object> iterator = response.result().bodyAsJsonArray().iterator();
                while(iterator.hasNext()){
                    Object obj = iterator.next();
                    JsonObject jsonPerson = (JsonObject) obj ;
                    logger.debug("personId: {}", jsonPerson.getString("id"));
                    Person person = new Person();
                    person.setId(jsonPerson.getString("id"));

                    String url2 = wshost+"/persons/"+jsonPerson.getString("id");
                    logger.info("Calling ws to get person details for : {}", jsonPerson.getString("id"), url2);
                     client.getAbs(url2).send(response2 -> {
                        if (response2.succeeded() && response2.result().statusCode()==200) {

                            JsonObject jsonDetails = response2.result().bodyAsJsonObject();
                            person.setDetail(jsonDetails);
                            personList.add(person);
                            logger.info("person is {} ", person);
                            logger.info("iterator.hasNext():{}", iterator.hasNext());


                        }
                        else{
                            routingContext.response().setStatusCode(500);
                            routingContext.response().end(buildError("Failed to get json ", 600).encode());
                        }

                    });

                };
                logger.info("personList: {} ", personList);
                logger.info("personList size {} ", personList.size());
                routingContext.response().setStatusCode(200).end(new JsonArray(personList).toString());
            } else {
                logger.error("Cannot get persons");
                routingContext.response().setStatusCode(500);
                routingContext.response().end(buildError("Failed to get persons", 100).encode());
            }
        } catch (Exception e) {
            e.printStackTrace();
            routingContext.response().setStatusCode(500);
            routingContext.response().end(buildError("Exception in API- Failed to get get persons for fleet "+routingContext.request().headers().get("fleet"), 300).encode());
        }

    });

}

First of all, you don't call your host only twice. 首先,您不会只两次呼叫主机。 You call it n+1 times, per number of persons in your initial request. 您将其称为n + 1次,即您最初请求中的人数。

Simplest way to achieve what you need is to count the number of persons you expect to get: 实现您所需的最简单方法是计算您希望获得的人数:

                int expected = response.result().bodyAsJsonArray().size();

                Iterator<Object> iterator = response.result().bodyAsJsonArray().iterator();
                while(iterator.hasNext()){
                    Object obj = iterator.next();
                    JsonObject jsonPerson = (JsonObject) obj ;
                    logger.debug("personId: {}", jsonPerson.getString("id"));
                    Person person = new Person();
                    person.setId(jsonPerson.getString("id"));

                    String url2 = wshost+"/persons/"+jsonPerson.getString("id");
                    logger.info("Calling ws to get person details for : {}", jsonPerson.getString("id"), url2);
                    client.getAbs(url2).send(response2 -> {
                        if (response2.succeeded() && response2.result().statusCode()==200) {

                            JsonObject jsonDetails = response2.result().bodyAsJsonObject();
                            person.setDetail(jsonDetails);
                            personList.add(person);
                            logger.info("person is {} ", person);
                            logger.info("iterator.hasNext():{}", iterator.hasNext());

                            // That's the last one
                            if (personList.size() == expected) {
                                // Only now complete the request
                                routingContext.response().setStatusCode(200).end(new JsonArray(personList).toString());
                            }
                        }
                        else{
                            routingContext.response().setStatusCode(500);
                            routingContext.response().end(buildError("Failed to get json ", 600).encode());
                        }

                    });

                };
                logger.info("personList: {} ", personList);
                logger.info("personList size {} ", personList.size());
               // Moved inside callback

Other way would be to use CompositeFuture: http://vertx.io/docs/vertx-core/groovy/#_concurrent_composition 其他方法是使用CompositeFuture: http : //vertx.io/docs/vertx-core/groovy/#_concurrent_composition

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM