java - Spring Reactive - 重用 Mono 值
问题描述
我有一系列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();
只需致电供应商一次即可提供所需的结果。
推荐阅读
- networking - 是否可以在 Keycloak 的查询字符串中编辑“代码”参数?
- excel - 需要从分隔的 Excel 字符串中删除不匹配的文本
- hash - 我们可以反转第二个 sha256 哈希吗?
- javascript - Angular 7 HttpHeaders CORS 问题
- c - 如何更改嵌套 for 循环中的行和列索引?
- javascript - ASP.NET MVC - 使用 Jquery 追加 HTML 后,DropDownList 值未定义
- react-select - 如何从 react-select 中的一长串选项中有效地进行选择
- xcode - 从网上复制的十六进制颜色代码在 swift 中用作主要故事板背景时出现不同?
- swift - UIActivityViewController iOS12.2:奇怪的活动类型标题
- scala - 在 Scala 中处理和抛出异常