java - .switchIfEmpty() 急切地求值有什么意义?

标签 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);
  }

输出为:

In Here (printed immediately)
5 (after 5s)

最佳答案

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

组装时间是您通过构建操作符链来创建管道的时间。此时,您的发布商尚未订阅,您需要迫切地思考。

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

有关此内容的更多信息,请参阅 great article作者:西蒙·巴斯莱。

正如 @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;
    });
}

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);
}

请注意,您原来的解决方案也完全没问题。您只需要知道返回 Mono 之前的代码是在汇编时执行的。

关于java - .switchIfEmpty() 急切地求值有什么意义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57870706/

相关文章:

java - 根据属性值从单个对象列表重建列表

java - 内部循环不打印单行矩阵的列Java intellij

javascript - 如何在 RxJS 中通过 ID 去抖

reactjs - 单击外部 url 的图像react.js

reactive-programming - Reactor Flux replay(int History) 方法未按预期工作

java - 将本地软件转换为在线软件

javascript - 有没有办法访问导入组件的 propTypes 和 defaultProps?

java - 使用 WebClient/Spring Boot 2 将 REST 响应映射到 Mono<SomeClass> 的正确方法

java - Spring 网络客户端: retry with backoff on specific error

java - ListView 在 Fragment 中不起作用