Mono 的 doOnSuccess 与 doOnNext 之间有区别吗?

Is there a difference between doOnSuccess vs doOnNext for a Mono?

假设您有 Mono<Integer> someIntegerSource = Mono.just(5) 并且您想将其分配给一个变量。

这些代码片段之间有区别吗?

案例一:doOnSuccess

someIntegerSource.doOnSuccess(number -> this.myNumber = number)

案例 2:doOnNext

someIntegerSource.doOnNext(number -> this.myNumber = number)

案例 3:doOnSuccess + 然后(因为我想在发出单声道完成之前完成分配)

someIntegerSource.doOnSuccess(number -> this.myNumber = number).then()

阅读 class Mono 的文档并查看图表。他们对行为的解释非常清楚。几乎没有明显的差异,但它们仍然是:

  • Mono::doOnNext 在数据 成功发射 时触发,这意味着数据可用且存在。
  • Mono::doOnSuccessMono 成功完成 时触发 - 结果是 Tnull,这意味着正在处理无论数据状态如何,它本身都成功完成并执行,尽管数据不可用或不存在但管道本身成功。
  • Mono::then 作为方法链的结尾 returns Mono<Void> 完成和错误信号。
    • 注意这里有效载荷被主动丢弃,这就是为什么 Mono<T> 变成 Mono<Void> 的原因。注意上面的两种方法不会丢掉payload。

这个答案缺少适当的说明性示例,因此我将对其进行修复:

非空 Mono

一个持有值的Mono在数据发送成功时触发doOnNext。这可能会使 doOnSuccess 混淆,但与此类触发器相反,当发出 any 成功值(包括空 Mono 时,会触发 doOnNext,这仍然有效。

Mono.just("Hello World")
    .doOnNext(i -> System.out.println("On next: " + i))
    .doOnSuccess(i -> System.out.println("On success: " + i))
    .doOnError(i -> System.out.println("On error: " + i))
    .block();
On next: Hello World
On success: Hello World

空单声道

记住,虽然 Mono 是空的 (Mono.empty()),它仍然是触发 doOnNext 的有效响应,但不是 doOnSuccess,一个空的 Mono 可以理解为有效响应,但不代表包含有用值的所需输出。它的工作原理与 Optional.empty() 相同。 Mono 成功但没有触发 doOnNext 的实际有用值,因为它根本不发出任何值。

Mono.empty()
    .doOnNext(i -> System.out.println("On next: " + i))
    .doOnSuccess(i -> System.out.println("On success: " + i))
    .doOnError(i -> System.out.println("On error: " + i))
    .block();
Mono.just("Hello World")
    .mapNotNull(s -> null)
    .doOnNext(i -> System.out.println("On next: " + i))
    .doOnSuccess(i -> System.out.println("On success: " + i))
    .doOnError(i -> System.out.println("On error: " + i))
    .block();

两者的结果相同:

On success: null

错误的单声道

为了完整起见,与空 Mono 进行对比,错误不会触发 doOnNextdoOnSuccess,而是触发 doOnError

Mono.error(new RuntimeException("Something wrong"))
    .doOnNext(i -> System.out.println("On next: " + i))
    .doOnSuccess(i -> System.out.println("On success: " + i))
    .doOnError(i -> System.out.println("On error: " + i))
    .block();
On error: java.lang.RuntimeException: Something wrong