像这样重新分配反应器 Publisher Mono 有什么问题吗?

Is there anything wrong with reassigning a reactor Publisher Mono like this?

这有什么问题吗?

public static void test3() {
  Mono<String> mono = Mono.just("");

  System.out.println(mono);
  for(int i=1; i<10; i++) {
    mono = updateMono(mono, i);
    System.out.println(mono);
  }

  mono.subscribe((s) -> System.out.println(s));
}

private static Mono<String> updateMono(Mono<String> mono, int i) {
  return mono
      .flatMap(s -> {
        if (i % 2 == 0) {
          return Mono.just(s + "-" + Integer.toString(i));
        } else {
          return mono;
        }
      });
}

它打印出预期的输出

-2-4-6-8

我想我是在问是否有任何我没有考虑到的意外或副作用

这里查询的重点似乎是使用命令式循环来更新 mono 引用。

它本身没有什么错误,但我发现从风格的角度来看,如果可能的话最好避免使用它——这意味着你不能只是 return单个反应链,你必须声明它,强制修改它任意次数,然后 return 它。

显然这是一个人为的例子,但通常可以采取不同的策略来生成更清晰的代码,具体取决于情况:

  • 您可以选择使用 Flux 并减少它,例如:

     Flux.range(1, 9)
             .filter(i -> i % 2 == 0)
             .map(i -> Integer.toString(i))
             .reduce((i1, i2) -> i1 + "-" + i2)
             .subscribe(System.out::println);
    
  • 您可以将循环重构为一个单独的方法,然后使用 transform,引用该方法,以至少保持主要反应链的流动;

  • 如果“真实世界”示例更自然地递归而不是迭代,则切换到使用 Flux 然后使用 expand()expandDeep() 将是最合乎逻辑的选择。

当然,如果它看起来很清楚并且您对此感到满意,那么在反应式管道中您肯定可以做更糟糕的事情 - 但在我遇到的大多数真实案例中,通常会有更好的提出问题的方式避免了命令式循环的需要。