两个单声道与条件的组合

Combination of two Mono with condition

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

如果第一个的结果满足某些条件以节省时间并避免不必要的网络调用,"cancel" 第二个 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
    }

}

更新:

为了更清楚,我们假设 trivialResult 在 1 秒内出现,nonTrivialResult 在 2 秒内出现。我想在 trivialResult.size > 5 的情况下在 1 秒内获得最终结果,否则在 2 秒内获得最终结果。

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

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

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

return trivialResultMono
        .filter(trivialResult -> trivialResult.size > 5)
        .switchIfEmpty(Mono.zip(...))

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);

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

您可以使用 flatMapmap 实现此目的:

trivial.flatMap(trivialResult -> {
  if (trivialResult.size > 5) {
    return Mono.just(trivialResult);
  } else {
    return nonTrivial.map(nonTrivialResult -> trivialResult + nonTrivialResult);
  }
});