在Mono中,doOnSuccess和doOnNext有区别吗?

22

假设你有一个Mono<Integer> someIntegerSource = Mono.just(5),你想将它分配给一个变量。

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

情况1: doOnSuccess

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

案例2:doOnNext

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

第三种情况:使用doOnSuccess + then(因为我希望在发出单体的完成信号之前,分配完成)

someIntegerSource.doOnSuccess(number -> this.myNumber = number).then()
1个回答

61
阅读Mono类的文档并查看图表。它们的差异并不像它们看起来那么微妙。
  • Mono::doOnNext在数据成功发射时触发,这意味着数据可用且存在。
  • Mono::doOnSuccessMono成功完成时触发 - 结果可以是Tnull,这意味着处理本身成功完成,无论数据的状态如何,即使数据不可用或不存在,但管道本身仍然执行。
  • Mono::then作为方法链的末端,在完成和错误信号上返回Mono<Void>
    • 请注意,此处有效载荷被主动丢弃,因此从Mono<T>变为Mono<Void>。请注意,上述两种方法不会丢弃有效载荷。
跟着下面的例子来看:
非空的 Mono
当一个带有值的 Mono 成功发射数据时,会触发 doOnNext。这可能会让人感到困惑,因为与此相反,doOnSuccess 只在成功触发时才会执行,而 doOnNext 则在任何成功的值被发射时都会执行,包括空的 Mono,这也是有效的。
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是空的(Mono.empty()),但它仍然是一个有效的响应,会触发doOnSuccess,但不会触发doOnNext。一个空的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

为了完整性起见,与空的Mono形成对比,错误的Mono既不触发doOnNext也不触发doOnSuccess,而是触发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

关于then的一点说明
方法Mono::then可以没有参数,也可以接受Mono<V>作为重载变体,前者会丢弃先前的结果并提供一个新的Mono<VoidMono<V>
Mono.empty()
    .then()
    .doOnSuccess(i -> System.out.println("On success: " + i))
    .doOnError(i -> System.out.println("On error: " + i))
    .block();

Mono.empty()
    .then(Mono.just("Good bye"))
    .doOnSuccess(i -> System.out.println("On success: " + i))
    .doOnError(i -> System.out.println("On error: " + i))
    .block();

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

Mono.error(new RuntimeException("Something wrong"))
    .then(Mono.just("Good bye"))
    .doOnSuccess(i -> System.out.println("On success: " + i))
    .doOnError(i -> System.out.println("On error: " + i))
    .block();

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

On success: null
On success: Good bye
On success: Good bye
On error: java.lang.RuntimeException: Something wrong
On error: java.lang.RuntimeException: Something wrong

我已经用更好的例子更新了答案。 - Nikolas Charalambidis
5
这是网络上描述这些差异的最佳分解之一。 - S.B.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接