我使用Mono
进行了一系列flatMap
转换。我设法将生产代码简化为以下测试用例:
@Test
public void test() {
AtomicInteger iCounter = new AtomicInteger(1);
Mono<String> iValueMono = Mono.fromSupplier(() -> {
int iValue = iCounter.getAndIncrement();
System.out.println("iValueMono CALL: " + iValue);
return String.valueOf(iValue);
});
Mono<String> resultMono = Mono.just("X")
.flatMap(append(iValueMono))
.flatMap(append(iValueMono));
StepVerifier.create(resultMono)
.consumeNextWith(result -> assertThat(result).isEqualTo("X11"))
.expectComplete()
.verify();
}
private Function<String, Mono<String>> append(Mono<String> sMono) {
return s -> sMono.map(v -> s + v);
}
打印:
iValueMono CALL: 1
iValueMono CALL: 2
org.junit.ComparisonFailure:
Expected :"X11"
Actual :"X12"
我以为-现在我看到这是不正确的-每次我在
iValueMono
调用中映射append()
时,供应商都会重新执行以产生新值。我无法更改生产代码中iValueMono
的实现方式(例如,使其有状态地存储值)。如何实现此方法,以便仅调用一次价值提供者,并得到最终结果“X11”?当然,我对一种无阻塞的反应式方法感兴趣。
最佳答案
使用 Mono.cache()
是答案:
将此Mono转换为热源,并缓存最后发出的信号以供进一步的订户使用。
使用它:
Mono<String> iValueMono = Mono.fromSupplier(() -> {
int iValue = iCounter.getAndIncrement();
System.out.println("iValueMono CALL: " + iValue);
return String.valueOf(iValue);
}).cache();
提供一次只致电供应商的预期结果。