我如何等待List <Mono>得到解决?

时间:2019-06-29 07:36:15

标签: java reactive-programming spring-webflux

我希望能够等待Monos列表得到解决,并且在最后一个元素完成后,继续进行另一个异步调用

    public Mono<Artist> getArtistInfo(String id) {
   //Call API1
    Mono<MusicResponse> musisResponseMono = webClientBuilder.build().get().uri(uri + "\"+ id).
            retrieve().bodyToMono(MusicResponse.class);

    //1.async handler for the first call
    return musisResponseMono.flatMap(musicRes ->{

        Artist artist = new Artist();
        List<Albums> albums =musicRes.getAlbums();

        //make mutiple concurrent API calls to API2
        albums.stream().forEach( album -> {
            webClientBuilder.build().get().uri("API 2 URL").
                    retrieve().bodyToMono(Covers.class)
                    .subscribe(cover ->  artist.getAlbums().add(cover.getImage()));


        });


//call API3 - want to wait untill all API calls 2 are completed
return webClientBuilder.build().get().uri("API3 URL).
                retrieve().bodyToMono(Profiles.class).map( profileRes -> artist.setDescription(profileRes.getDescription());


    }

}

问题在于API调用3可能会在第二个调用的每个元素都返回之前返回。我想我要寻找的是在Spring Webflux上下文中在Javascipt中等待asycn

1 个答案:

答案 0 :(得分:2)

我认为这应该有效。

我们首先获取艺术家并绘制响应。在映射过程中,我们获取每个专辑的封面并获得List<Mono<Cover>>博克。

然后,我们将它们合并到Flux#merge中,并在每个Cover可用时发出它们。这样我们就可以在每次发射doOnNext并将它们附加到艺术家上。

完成后,我们只需then并返回艺术家对象。

这些事件链之后,我们可以doOnSuccess进行第二次提取,并将更多信息附加到Artist对象。

public Mono<Artist> getArtistInfo(String id) {
    return webClient.get()
            .uri("/artist")
            .retrieve()
            .bodyToMono(ArtistResponse.class)
            .flatMap(artistResponse -> {
                final Artist artist = new Artist();
                return Flux.fromIterable(artistResponse.getAlbums())
                        .parallel(2)
                        .runOn(Schedulers.parallel())
                        .map(albums -> webClient.get()
                                .uri("artist/albums")
                                .retrieve()
                                .bodyToMono(Covers.class))
                        .doOnNext(coversMono -> coversMono
                            .doOnSuccess(covers -> artist.getAlbums().add(covers)))
                        .thenReturn(artist);
            })
            .doOnSuccess(artist -> webClient.get()
                    .uri("/artist/profile")
                    .retrieve()
                    .bodyToMono(Profiles.class)
                    .doOnSuccess(profiles -> artist.setDescription(profiles.getDescription())));
}

没有运行代码,因此不能保证,但是至少它可以为您提供一些见识,并为您迈出一步。