有人可以解释 Reactor Mono 流中 .then() 方法的注意事项吗?

Jam*_*ald 0 lambda spring reactive-programming java-8 project-reactor

我下面有两个测试函数,我希望返回相同的结果。第一个 (monoTest3) 在 '.then()' 方法中使用 lambda 表达式。第二个没有。

为什么我会得到我所做的结果?

使用 ReactiveX 和 lambda 表达式时有哪些注意事项?

在下面的代码中,monoTest3 产生

monoVoid called
Success
----
monoVoid2 called
Success
Run Code Online (Sandbox Code Playgroud)

和 monoTest4 产生(所需的结果):

monoVoid called
monoVoid2 called
Success
----
monoVoid2 called
monoVoid called
Success
Run Code Online (Sandbox Code Playgroud)

最后是代码。

private static Mono<Void> monoVoid() {
    System.out.println("monoVoid called");
    return Mono.empty();
}

private static Mono<Void> monoVoid2() {
    System.out.println("monoVoid2 called");
    return Mono.just("Hello").then();
}

@Test
public void monoTest3() throws Exception {
    monoVoid()
            .then( v -> monoVoid2())
            .doOnSuccess(v -> System.out.println("Success"))
            .block();

    System.out.println("----");

    monoVoid2()
            .then( v -> monoVoid())
            .doOnSuccess(v -> System.out.println("Success"))
            .block();
}

@Test
public void monoTest4() throws Exception {
    monoVoid()
            .then( MonoTest::monoVoid2 )
            .doOnSuccess(v -> System.out.println("Success"))
            .block();

    System.out.println("----");

    monoVoid2()
            .then(MonoTest::monoVoid)
            .doOnSuccess(v -> System.out.println("Success"))
            .block();

}
Run Code Online (Sandbox Code Playgroud)

Sim*_*slé 5

Mono.then(Function)实际上已被弃用,3.0.7并将在 中删除,3.1.0因为它的行为与 中的所有其他then方法略有不同Mono,因此我们预见到人们会像刚才那样感到困惑。

在 3.1.0(目前在里程碑 2 中,所以3.1.0.M2)它现在被称为flatMap,而将返回 a 的旧 flatMapFlux现在是flatMapMany

这更好地传达了正确的语义,如果您了解一点,flatMap那么您可以正确地推断出“continuation Mono”只能在sourceMono为 value时生成和订阅。

换句话说,调用Mono.just("foo").then().then(v -> {...})(3.0.x version) 或Mono.just("foo").then().flatMap(v -> {...})(3.1.0 version) 没有意义,因为第一个then()具有没有发出值的效果。如果没有值,则不会调用 lambda(它的作用是将值转换为延续 MonoMono.empty().then(v -> {})出于相同的原因调用没有任何意义。