简体   繁体   中英

How do I wait for a List<Mono> to get resolved?

I want to be able to wait for a List of Monos to get resolved and upon completion of the last element, proceed with another async call

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())
            );


    }
    
}

The problem is that API call 3 may return before every element of the second call is returned . I guess what I'm looking for is something like asycn await in Javascipt in the context of Spring Webflux

I think this should work.

We first fetch the artists and map the response. During the mapping we fetch each album cover and get a List<Mono<Cover>> bock.

We then merge these in a Flux#merge that will emit each Cover when they are available. So we can then on each emit doOnNext and attach these to the artist.

When that is done, we just then and return the artist object.

After these chain of events we can doOnSuccess our second fetch and attach more information to the Artist object.

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())));
}

Havn't run the code so can't guarantee it but at least it will give you some insight maybe and a step on the way.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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