我有一个通用方法,可以并行执行一堆请求,将它们发送到外部 Web api,并收集结果。
问题:调用者应该能够为 Web 请求的子例程提供成功和错误处理程序。但是如何?
示例:
public <Req, Rsp> List<Rsp> sendApiRequests(List<Req> requests, Class<Rsp> type) {
return Flux.fromIterable(requests)
.flatMap(req -> webClient.post()
.uri(uri)
.bodyValue(req)
.retrieve()
.bodyToMono(type)
.//TODO how can I add a generic handler methods here?
.)
.filter(rsp -> rsp.success() && rsp.results > 0) //some common filters
.collectList()
.block();
}
调用者应该能够提供一个非常可能的子程序。例如,它可以提供.doOnSuccess()
、.doOnerror()
或.onErrorMap()
函数。还有任何其他或全部。
伪代码:
sendApiRequests(req, MyDto.class, req -> <subroutine>.doOnSuccess(..)
.doOnError(..)
.onErrorResume(..));
这可能吗?因为我没有将 Mono
请求中的 webClient.post()
暴露给调用者,所以我不知道如何在其上链接处理程序方法。
答案 0 :(得分:1)
您可以在此处使用变换运算符。我不会称之为添加“消费者”,而是在反应管道中的特定点插入额外的运算符。它看起来像:
public String blockingCall(Function<Mono<String>, Publisher<String>> transformer) {
return Mono.just("hi")
.transform(transformer)
.block();
}
并像这样使用它:
blockingCall(it -> it.doOnSuccess(...).doOnError(...))
答案 1 :(得分:1)
您应该使用 Mono#transform
。来自 Reactor 的 documentation:
transform 运算符让您可以将一段运算符链封装到一个函数中。该函数在汇编时应用于原始运算符链,以使用封装的运算符对其进行扩充。这样做对序列的所有订阅者应用相同的操作,基本上等同于直接链接操作符。
就你而言:
public <Req, Rsp> List<Rsp> sendApiRequests(List<Req> requests, Class<Rsp> type, Function<Mono<Rsp>, Mono<Rsp>> subroutine) {
return Flux.fromIterable(requests)
.flatMap((Req req) -> webClient.post()
.uri(uri)
.bodyValue(req)
.retrieve()
.bodyToMono(type)
.transform(subroutine)
)
.filter(rsp -> rsp.success() && rsp.results > 0) //some common filters
.collectList()
.block();
}