所以,我正在尝试使用 Webflux,并且有一个场景“检查对象是否存在;如果存在,则执行操作,否则 - 指示错误”。
可以在reactor中写成:
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
忽略参数(这似乎更具可读性)。我的观点是,在可读性和代码质量方面,这两种方法都有优点和缺点。
所以,总结如下:
然后使用
- 优点
- 语义正确
- 缺点
- 在许多情况下(如上面)需要包装在特别的 Mono/Flux 中
使用平面 map
- 优点
- 简化了持续的“快乐场景”代码
- 缺点
- 语义不正确
这两种方法还有哪些其他优点/缺点?选择运营商时应该考虑什么?
我找到了this reactor issue这表明速度没有真正的差异。
最佳答案
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()
不关心前面的事件顺序。它只关心完成事件:
这就是为什么,在您的示例中,使用哪一个并不重要。但是,在其他情况下您可能会做出相应的选择。
您可能还会找到Which operator do I need?项目 react 堆引用部分很有帮助。
关于java - 我应该使用 "then"还是 "flatMap"来控制流?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49710432/