首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Quarkus Mutiny Uni/Multi等待请求响应完成

Quarkus Mutiny Uni/Multi等待请求响应完成
EN

Stack Overflow用户
提问于 2022-11-07 14:01:44
回答 2查看 195关注 0票数 0

这个问题我找不到正确的解决办法,我被困住了。假设我有这样的方法

代码语言:javascript
复制
    @GET
    @Path("/testingAsync")
    public Uni<List<String>> testingMutiny() {
        List<String> completeList = new ArrayList<>();
        completeList.add("hello");
        completeList.add("RestEasy");

        List<String> finalList = new ArrayList<>();

        completeList.forEach(e -> Uni.createFrom().item(e)
                .onItem().delayIt().by(Duration.ofMillis(10000))
                .map(value -> finalList.add(value.toUpperCase()))
                .subscribe().asCompletionStage());


        return Uni.createFrom().item(finalList);
    }

正如您所看到的,这个方法很简单,它只是从一个列表中获取值并将它们添加到第二个列表中,但是问题是什么?当您添加等待的.onItem().delayIt().by(Duration.ofMillis(10000))时,程序将返回一个空列表,一段时间后,它将只更新列表。我创建这个方法是为了模拟一个请求,这个请求的响应有一些延迟。

假设您使用两个不同的Uni访问了两个URL,然后尝试将它们组合起来,并将它们作为一个Uni返回。问题是,如果这两个URL中的一个由于某种原因而延迟,我们将返回列表为空,但我不希望这种情况发生,我希望列表完成100%,或者返回一个错误,如果它需要一段时间。

最好的办法是什么?我了解到,如果您添加了await(),您就阻塞了主线程,并且丢失了使用反应性库的所有价值,但我仍然找不到一种方法让它工作

编辑

我已经发现,我试图调用的外部URL需要大约5秒的时间来完成这项工作,所以我希望在创建Uni时停止代码,并在收到服务器的答复后继续。我在他们的文档(这里)中看到,我也可以调用await.indefinitely,但我接收到了The current thread cannot be blocked: vert.x-eventloop-thread-14。如何等待服务器的响应?

编辑2

我明白,有了字符串,我的问题就不那么有意义了,所以假设我有下面一个

代码语言:javascript
复制
    @GET
    @Path("/testingAsync")
    public Uni<List<Car>> testingMutiny() {

        //ALL THIS IS IN A FOR EACH FOR EVERY CAR

            //HIT ENDPOINT GET DOORS
            Uni<List<JsonObjectCar>> carDoorsUni = getDoors(variable1,
                    variable2, variable3);

            //HIT ENDPOINT GET WHEELS
            Uni<List<JsonObjectCar>> carWheelsUni = getWheels(variable1,
                    variable2, variable3);

            //HIT ENDPOINT GET WINDOWS
            Uni<List<JsonObjectCar>> carWindowsUni = getWindows(variable1,
                    variable2, variable3);

            Uni.combine()
                    .all()
                    .unis(carDoorsUni, carWheelsUni, carWindowsUni)
                    .combinedWith((carDoors, carWheels, carWindows) -> {
                        //Check if cardoors is present and set the doors into the car object
                        Optional.of(carDoors)
                                .ifPresent(val -> car.setDoors(val.getDoors()));
                        Optional.of(carWheels)
                                .ifPresent(val -> car.setWheels(val.getWheels()));
                        Optional.of(carWindows)
                                .ifPresent(val -> car.setWindows(val.getWindows()));

                        return car;
                    }).subscribe().with(e-> System.out.println("Okay it worked"));
            
          //END OF FOR EACH 
            
            
            //Return car (Should have been returned with new doors / wheels/ windows but instead its empty)
        return Uni.createFrom().item(car);

    }

正如您在上面的代码中所看到的,它应该命中门/轮/窗的一些端点,并将它们设置到可变的汽车中,但实际上,所发生的情况是,汽车是空的,因为其中一个端点被延迟了,所以我返回一辆没有这些值的汽车。我想首先更新car对象,然后实际返回它。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-11-08 14:40:36

您可以这样重写该方法:

代码语言:javascript
复制
    @GET
    @Path("/testingAsync")
    public Uni<List<String>> testingMutiny() {
        List<Uni<String>> unis = new ArrayList<>();
        List.of("hello", "RestEasy").forEach( e -> {
            unis.add( Uni.createFrom().item( e )
                .onItem().delayIt().by( Duration.ofMillis( 10000 ) ) );
        } );

        return Uni.combine().all().unis( unis )
                .combinedWith( list -> (List<String>) list);
    }

注意,当您编写反应性代码时,您希望避免使用.await().indefinetly。无论如何,在使用Quarkus时不应该需要它,因为它识别异步API并相应地解释结果。

在使用Quarkus时,您也不需要订阅Uni或Multi,原因也是一样的。

基于前面的示例,您可以用端点重写用例,如下所示:

代码语言:javascript
复制
    @GET
    @Path("/testingAsync")
    public Uni<Car> testingMutiny() {
            Uni<List<JsonObjectCar>> carDoorsUni = getDoors(variable1, variable2, variable3);
            Uni<List<JsonObjectCar>> carWheelsUni = getWheels(variable1,variable2, variable3);
            Uni<List<JsonObjectCar>> carWindowsUni = getWindows(variable1,variable2, variable3);

            return Uni.combine()
                    .all()
                    .unis(carDoorsUni, carWheelsUni, carWindowsUni)
                    .combinedWith(list -> {
                        // Result of carDoorsUni
                        List<JsonObjectCar> carDoors = list.get(0);

                        // Result of carWheelsUni
                        List<JsonObjectCar> carWheels = list.get(1);

                        // Result of carWindowsUni
                        List<JsonObjectCar> carWindows = list.get(2);
                        
                        // Create a car instance with the previous results
                        Car car = createCar(...);

                        // You can also return a list of cars, but you need to change the return type of testingMutiny to Uni<List<Car>>
                        return car;
                    })
                    .invoke( () -> System.out.println("Okay it worked"));
    }
票数 2
EN

Stack Overflow用户

发布于 2022-11-08 12:23:46

您返回一个列表,但是Uni上的异步处理延迟了,所以您的列表将为空。

您应该尝试从创建的管道返回一个Uni (还可以看到collect()toUni()将其放入列表),而不是执行订阅、收集结果并将其重新包装为Uni

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74347822

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档