Преобразование Spring Webflux Mono в любую, желательно без блокировки?
Я использую Kotlin и Arrow и веб-клиент из spring-webflux
, То, что я хотел бы сделать, это преобразовать экземпляр Mono в Either.
Either
экземпляр создается путем вызова Either.right(..)
когда ответ WebClient
успешно или Either.left(..)
когда WebClient
возвращает ошибку.
То, что я ищу, это метод в Mono
похож на Either.fold (..), где я могу отобразить успешный и ошибочный результат и вернуть другой тип, чем Mono
, Примерно так (псевдокод не работает):
val either : Either<Throwable, ClientResponse> =
webClient().post().exchange()
.fold({ throwable -> Either.left(throwable) },
{ response -> Either.right(response)})
Как идти?
2 ответа
Я не очень знаком с этой библиотекой Arrow и с типичным сценарием ее использования, поэтому здесь я буду использовать фрагменты Java.
Сначала я хотел бы сначала указать, что этот тип кажется блокирующим и не ленивым (в отличие от Mono
). Переводя Mono
этот тип означает, что вы сделаете свой код блокирующим и что вам не следует этого делать, например, в середине обработчика контроллера, или вы заблокируете весь свой сервер.
Это более или менее эквивалентно этому:
Mono<ClientResponse> response = webClient.get().uri("/").exchange();
// blocking; return the response or throws an exception
ClientResponse blockingResponse = response.block();
При этом, я думаю, вы должны быть в состоянии преобразовать Mono
к этому типу путем вызова block()
на это и try/catch
блокировать вокруг него или превратить его сначала в CompletableFuture
во-первых, как:
Mono<ClientResponse> response = webClient.get().uri("/").exchange();
Either<Throwable, ClientResponse> either = response
.toFuture()
.handle((resp, t) -> Either.fold(t, resp))
.get();
Возможно, есть лучшие способы сделать это (особенно с помощью встроенных функций), но все они должны включать блокировку Mono
на первом месте.
Здесь нет fold
метод на Mono
но вы можете достичь того же, используя два метода: map
а также onErrorResume
, Было бы что-то вроде этого:
val either : Either<Throwable, ClientResponse> =
webClient().post()
.exchange()
.map { Either.right(it) }
.onErrorResume { Either.left(it).toMono() }