两个Mono与条件的组合

时间:2019-05-15 11:40:07

标签: reactive-programming spring-webflux project-reactor

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

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

如果第一个Mono来自第一个Mono的想法满足某些条件,可以节省时间并避免不必要的网络呼叫,那么该想法可以“取消”。如果第一个zip的结果不够Mono,第二个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 } } 的结果。

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

trivialResult.size > 5

更新:

更清楚地说,假设trivialResult在1秒内出现,nonTrivialResult在2秒内出现。我想在Mono.zip(trivialResultMono, nonTrivialResultMono)的情况下在1秒内获得最终结果,否则在2秒内得到最终结果。

仅使用filter + switchIfEmpty,我将始终在2秒内获得最终结果。

如果使用trivialResult.size > 5,则使用const routes: Routes = [ { path: '', redirectTo: 'overview', pathMatch: 'full' }, { path: 'overview', loadChildren: './overview/overview.module#OverviewPageModule' }, { path: 'home', loadChildren: './home/home.module#HomePageModule' }, /... ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) 将花费1秒,否则使用3秒。如果我错了,请纠正我。

2 个答案:

答案 0 :(得分:1)

您可以过滤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的操作

答案 1 :(得分:0)

您可以使用flatMapmap来实现:

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