Как мне дождаться разрешения списка <Mono>? - PullRequest
0 голосов
/ 29 июня 2019

Я хочу иметь возможность дождаться разрешения списка моносов и после завершения последнего элемента продолжить другой асинхронный вызов

    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 может возвращаться до того, как будет возвращен каждый элемент второго вызова. Я думаю, что я ищу что-то вроде asycn в Javascipt в контексте Spring Webflux

1 Ответ

2 голосов
/ 29 июня 2019

Я думаю, что это должно работать.

Сначала выбираем художников и отображаем ответ. Во время картирования мы берем обложку каждого альбома и получаем List<Mono<Cover>> бок.

Затем мы объединяем их в Flux#merge, который будет излучать каждый Cover, когда они будут доступны. Таким образом, мы можем затем на каждом излучении doOnNext и прикрепить их к исполнителю.

Когда это будет сделано, мы просто then и возвращаем объект Artist.

После этой цепочки событий мы можем 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())));
}

Не запускал код, поэтому не могу гарантировать его, но, по крайней мере, он даст вам некоторое понимание и, возможно, шаг вперед.

...