将 Spring Webflux Mono 转换为 Either,最好不要阻塞?
Transforming a Spring Webflux Mono to an Either, preferably without blocking?
我正在使用 Kotlin 和 Arrow and the WebClient from spring-webflux
. What I'd like to do is to transform a Mono instance to an Either。
Either
实例是在WebClient
响应成功时调用Either.right(..)
或WebClient
return响应时调用Either.left(..)
创建的这是一个错误。
我正在寻找的是 Mono
中类似于 Either.fold(..) 的方法,我可以在其中映射成功和错误的结果,并且 return 与 Mono
。像这样的东西(伪代码不起作用):
val either : Either<Throwable, ClientResponse> =
webClient().post().exchange()
.fold({ throwable -> Either.left(throwable) },
{ response -> Either.right(response)})
怎么办?
我不太熟悉 Arrow 库,也不熟悉它的典型用例,所以我将使用 Java 片段来说明我的观点。
首先我想首先指出这种类型似乎是阻塞的而不是惰性的(不像 Mono
)。将 Mono
转换为该类型意味着您将使您的代码阻塞并且您不应该这样做,例如,在 Controller 处理程序的中间,否则您将阻塞整个服务器。
这或多或少相当于:
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
上的阻塞。
Mono
上没有 fold
方法,但您可以使用以下两种方法实现相同的方法:map
和 onErrorResume
。它会是这样的:
val either : Either<Throwable, ClientResponse> =
webClient().post()
.exchange()
.map { Either.right(it) }
.onErrorResume { Either.left(it).toMono() }
我正在使用 Kotlin 和 Arrow and the WebClient from spring-webflux
. What I'd like to do is to transform a Mono instance to an Either。
Either
实例是在WebClient
响应成功时调用Either.right(..)
或WebClient
return响应时调用Either.left(..)
创建的这是一个错误。
我正在寻找的是 Mono
中类似于 Either.fold(..) 的方法,我可以在其中映射成功和错误的结果,并且 return 与 Mono
。像这样的东西(伪代码不起作用):
val either : Either<Throwable, ClientResponse> =
webClient().post().exchange()
.fold({ throwable -> Either.left(throwable) },
{ response -> Either.right(response)})
怎么办?
我不太熟悉 Arrow 库,也不熟悉它的典型用例,所以我将使用 Java 片段来说明我的观点。
首先我想首先指出这种类型似乎是阻塞的而不是惰性的(不像 Mono
)。将 Mono
转换为该类型意味着您将使您的代码阻塞并且您不应该这样做,例如,在 Controller 处理程序的中间,否则您将阻塞整个服务器。
这或多或少相当于:
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
上的阻塞。
Mono
上没有 fold
方法,但您可以使用以下两种方法实现相同的方法:map
和 onErrorResume
。它会是这样的:
val either : Either<Throwable, ClientResponse> =
webClient().post()
.exchange()
.map { Either.right(it) }
.onErrorResume { Either.left(it).toMono() }