这是因为switchIfEmpty接受Mono“按值”。这意味着,即使在您订阅单声道之前,此替代单声道的评估也已触发。
想象这样的方法:
Mono<String> asyncAlternative() { return Mono.fromFuture(CompletableFuture.supplyAsync(() -> { System.out.println("Hi there"); return "Alternative"; }));}如果您这样定义代码:
Mono<String> result = Mono.just("Some payload").switchIfEmpty(asyncAlternative());无论在流构建期间发生什么,它总是会触发替代方法。为了解决这个问题,您可以通过使用推迟第二个单声道的评估
Mono.defer
Mono<String> result = Mono.just("Some payload") .switchIfEmpty(Mono.defer(() -> asyncAlternative()));这样,仅当请求替代项时才打印“ Hi there”
UPD:
详细说明我的答案。您面临的问题与Reactor无关,而与Java语言本身以及它如何解析方法参数有关。让我们检查一下我提供的第一个示例中的代码。
Mono<String> result = Mono.just("Some payload").switchIfEmpty(asyncAlternative());我们可以将其重写为:
Mono<String> firstMono = Mono.just("Some payload");Mono<String> alternativeMono = asyncAlternative();Mono<String> result = firstMono.switchIfEmpty(alternativeMono);这两个代码段在语义上是等效的。我们可以继续展开它们,以查看问题所在:
Mono<String> firstMono = Mono.just("Some payload");CompletableFuture<String> alternativePromise = CompletableFuture.supplyAsync(() -> { System.out.println("Hi there"); return "Alternative"; }); // future computation already tiggeredMono<String> alternativeMono = Mono.fromFuture(alternativePromise);Mono<String> result = firstMono.switchIfEmpty(alternativeMono);如您所见,当我们开始编写
Mono类型时,将来的计算已经触发。为了防止不必要的计算,我们可以将我们的未来纳入延迟评估中:
Mono<String> result = Mono.just("Some payload") .switchIfEmpty(Mono.defer(() -> asyncAlternative()));哪个会解开
Mono<String> firstMono = Mono.just("Some payload");Mono<String> alternativeMono = Mono.defer(() -> Mono.fromFuture(CompletableFuture.supplyAsync(() -> { System.out.println("Hi there"); return "Alternative"; }))); // future computation deferedMono<String> result = firstMono.switchIfEmpty(alternativeMono);在第二个示例中,未来被困在一个懒惰的供应商中,并且仅在需要时才安排执行。



