急切评估.switchIfEmpty()有什么意义? [英] What's the point of .switchIfEmpty() getting evaluated eagerly?

查看:77
本文介绍了急切评估.switchIfEmpty()有什么意义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

即使我的信息流不为空,也将始终创建后备信息流?这样做的目的是什么?这是极不习惯的.

Even if my stream is not empty, the fallback stream would always be created? What's the intent behind doing this? This is extremely non-idiomatic.

另一方面,. onErrorResume 的计算是延迟的.

On the other hand, .onErrorResume is evaluated lazily.

有人可以向我解释为什么. switchIsEmpty 受到热切评价吗?

Could someone please explain to me why .switchIsEmpty is evaluated eagerly?

这是代码:

  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)

推荐答案

在这里您需要了解的是汇编时间和订阅时间之间的差异.

What you need to understand here is the difference between assembly time and subscription time.

组装时间是指通过构建操作员链来创建管道的时间.此时,您的发布者尚未订阅,您需要进行必要的思考.

Assembly time is when you create your pipeline by building the operator chain. At this point your publisher is not subscribed yet and you need to think kind of imperatively.

订阅时间是指您通过订阅触发执行并且数据开始流过管道的时间.在这种情况下,您需要对回调,lambda和延迟执行等做出反应.

Subscription time is when you trigger the execution by subscribing and the data starts flow through your pipeline. This is when you need to think reactively in terms of callbacks, lambdas, lazy execution, etc..

有关更多信息,请参见 SimonBaslé的精彩文章.

More on this in the great article by Simon Baslé.

正如@akarnokd在他的回答中提到的那样,由于未将 getFallback()方法定义为lambda,而只是常规方法调用,因此在汇编时必须强制调用 getFallback()方法.

As @akarnokd mentioned in his answer, the getFallback() method is called imperatively at assembly time since it is not defined as a lambda, just a regular method call.

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

You can achieve true laziness by one of the below methods:

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

1, You can use Mono.fromCallable and put your log inside the 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的执行和组装,直到订阅:

2, You can use Mono.defer and delay the execution and the assembling of your inner Mono until subscription:

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之前的代码是在汇编时执行的.

Note that your original solution is also perfectly fine. You just need to aware of that the code before returning the Mono is executed at assembly time.

这篇关于急切评估.switchIfEmpty()有什么意义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆