所以,我正在尝试使用Webflux并且我有一个场景“检查一个对象是否存在;如果是,那么做,否则 - 表示错误”。
这可以写在反应堆中:
public Mono<Void> handleObjectWithSomeId(Mono<IdType> id){
return id.
flatMap(repository::exists). //repository.exists returns Mono<Boolean>
flatMap(e -> e ? e : Mono.error(new DoesntExistException())).
then(
//can be replaced with just(someBusinessLogic())
Mono.fromCallable(this::someBusinessLogic)
);
}
或作为:
public Mono<Void> handleObjectWithSomeId(Mono<IdType> id){
return id.
flatMap(repository::exists). //repository.exists returns Mono<Boolean>
flatMap(e -> e ? e : Mono.error(new DoesntExistException())).
map(e -> this.someBusinessLogic()));
}
我们假设someBusinessLogic
的返回类型无法更改,且必须简单void
,而不是Mono<Void>
。
在这两种情况下,如果对象不存在,将生成相应的Mono.error(...)
。
虽然我理解then
和flatMap
具有不同的语义,但实际上我得到了相同的结果。即使在第二种情况下我使用flatMap
来反对它的含义,我也会跳过flatMap
和fromCallable
,而不是简单的map
使用忽略的参数(这看起来更具可读性) )。我的观点是,在可读性和代码质量方面,两个apporaches都有优点和缺点。
所以,这是一个总结:
使用
使用flatMap
这两种方法的其他优点/缺点是什么?选择运营商时应该考虑什么?
我发现this reactor issue表示速度没有实际差异。
答案 0 :(得分:1)
TL,DR:如果您关心以前计算的结果,可以使用map()
,flatMap()
或其他map
变体。否则,如果您只想完成上一个流,请使用then()
。
您可以通过在两种方法中调用.log()
来查看详细的执行日志:
public Mono<Void> handleObjectWithSomeId(Mono<IdType> id) {
return id.log()
.flatMap(...)
...;
}
与Project Reactor中的所有其他操作一样,then()
和flatMap()
的语义已经定义。上下文主要定义了这些运算符应如何协同解决您的问题。
让我们考虑一下您在问题中提供的背景。 flatMap()
的作用是,只要它获得一个事件,就会异步执行映射函数。
由于我们在问题中的最后一个Mono<>
之后有一个flatMap()
,它将提供我们忽略的先前单个计算的结果。请注意,如果我们改为Flux<>
,则会对每个元素进行计算。
另一方面,then()
并不关心前面的事件序列。它只关心完成事件:
这就是为什么,在你的例子中,你使用哪一个并不重要。但是,在其他情况下,您可以相应地选择。