.switchIfEmpty() 被急切地评估有什么意义?

Pra*_*dey 3 java reactive-programming project-reactor reactive

即使我的流不为空,回退流也会始终创建?这样做的意图是什么?这是非常不习惯的。

另一方面, 。onErrorResume被懒惰地评估。

有人可以向我解释为什么。switchIsEmpty热切评价?

这是代码:

  public static void main(String[] args) {
    Mono<Integer> m = Mono.just(1);
    m.flatMap(a -> Mono.delay(Duration.ofMillis(5000)).flatMap(p -> Mono.empty()))
        .switchIfEmpty(getFallback())
        .doOnNext(a -> System.out.println(a))
        .block();
  }

  private static Mono<Integer> getFallback() {
    System.out.println("In Here");
    return Mono.just(5);
  }
Run Code Online (Sandbox Code Playgroud)

输出是:

In Here (printed immediately)
5 (after 5s)
Run Code Online (Sandbox Code Playgroud)

Mar*_*nyi 10

这里需要了解的是组装时间和订阅时间的区别。

组装时间是您通过构建操作符链来创建管道的时间。此时您的发布者尚未订阅,您需要考虑一下势在必行。

订阅时间是您通过订阅触发执行并且数据开始流经您的管道的时间。这是您需要在回调、lambdas、延迟执行等方面进行被动思考的时候。

更多关于这方面的信息,请参阅Simon Baslé的精彩文章

正如@akarnokd 在他的回答中提到的,该getFallback()方法在汇编时被命令式调用,因为它没有定义为 lambda,只是一个常规的方法调用。

您可以通过以下方法之一实现真正的懒惰:

1,您可以使用Mono.fromCallable并将您的日志放在 lambda 中:

public static void main(String[] args) {
    Mono<Integer> m = Mono.just(1);

    m.flatMap(a -> Mono.delay(Duration.ofMillis(5000)).flatMap(p -> Mono.empty()))
     .switchIfEmpty(getFallback())
     .doOnNext(a -> System.out.println(a))
     .block();
}

private static Mono<Integer> getFallback() {
    System.out.println("Assembly time, here we are just in the process of creating the mono but not triggering it. This is always called regardless of the emptiness of the parent Mono.");
    return Mono.fromCallable(() -> {
        System.out.println("Subscription time, this is the moment when the publisher got subscribed. It is got called only when the Mono was empty and fallback needed.");
        return 5;
    });
}
Run Code Online (Sandbox Code Playgroud)

2,您可以使用Mono.defer和延迟执行和组装您的内部 Mono 直到订阅:

public static void main(String[] args) {
    Mono<Integer> m = Mono.just(1);
    m.flatMap(a -> Mono.delay(Duration.ofMillis(5000)).flatMap(p -> Mono.empty()))
     .switchIfEmpty(Mono.defer(() -> getFallback()))
     .doOnNext(a -> System.out.println(a))
     .block();
}

private static Mono<Integer> getFallback() {
    System.out.println("Since we are using Mono.defer in the above pipeline, this message gets logged at subscription time.");
    return Mono.just(5);
}
Run Code Online (Sandbox Code Playgroud)

请注意,您的原始解决方案也非常好。您只需要知道返回 Mono 之前的代码是在汇编时执行的。