两个 Mono 带条件的组合

NCh*_*hin 6 reactive-programming project-reactor spring-webflux

Mono我想根据某些条件合并两种结果。两者Mono都是调用的结果WebClient

  • 第一个是单个呼叫,期望快速响应。
  • 第二个是多个呼叫的组合,响应缓慢。

如果第一个结果满足某些条件,则“取消”第二个的想法Mono可以节省时间并避免不必要的网络调用。如果第一个Mono结果不够,zip则使用第二个Mono

一个 Kotlin 代码示例来解释我的想法:

fun getResult(): Mono<Result> {

    val trivialResultMono: Mono<Result> = webClient.getResult()

    val nonTrivialResultMono: Mono<Result> = webClient
            .getResult()
            .flatMap { webClient.getResult1(it) }
            .flatMap { webClient.getResult2(it) }
            .flatMap { webClient.getResult2(it) }

    //here I need to check if trivial result satisfies some condition,
    //for example trivialResult.size > 5 if it's true I just return
    //trivialResultMono from getResult() function, 
    //it it's false something like this:
    return Mono.zip(trivialResultMono, nonTrivialResultMono) { trivialResult, nonTrivialResult ->
        trivialResult + nonTrivialResult
    }

}
Run Code Online (Sandbox Code Playgroud)

更新:

为了更清楚,我们假设 trivialResult 在 1 秒内出现,nonTrivialResult 在 2 秒内出现。我希望在 1 秒内得到最终结果,否则trivialResult.size > 5在 2 秒内得到。

仅使用Mono.zip(trivialResultMono, nonTrivialResultMono)我总是会在 2 秒内得到最终结果。

如果使用filter + switchIfEmpty则需要 1 秒,trivialResult.size > 5否则需要 3 秒。如果我错了,请纠正我。

Ale*_*kin 1

您可以过滤trivialResultMono并应用switchIfEmpty运算符

return trivialResultMono
        .filter(trivialResult -> trivialResult.size > 5)
        .switchIfEmpty(Mono.zip(...))
Run Code Online (Sandbox Code Playgroud)

方法更新merge

Mono<Result> zipResultMono = Mono.zip...

return Flux.merge(
        trivialResultMono.map(trivialResult -> Tuples.of(1, trivialResult)),
        zipResultMono.map(zipResult -> Tuples.of(2, zipResult)))
        .filter(tuple ->
                (tuple.getT1().equals(1) && tuple.getT2().size > 5) ||
                        tuple.getT1().equals(2))
        .next()
        .map(Tuple2::getT2);
Run Code Online (Sandbox Code Playgroud)

如果 zipResult 的大小始终大于 5,您可以跳过转换为 Tuple2