java - 我应该使用 "then"还是 "flatMap"来控制流?

标签 java reactive-programming reactor

所以,我正在尝试使用 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(...)将被生产。

虽然我明白thenflatMap有不同的语义,实际上我得到了相同的结果。即使在第二种情况下我使用 flatMap与它的含义相反,我要跳过 flatMapfromCallable赞成简单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()所做的是,每当它收到事件时,它就会异步执行映射函数。

flatmap marble diagram

因为我们有 Mono<>最后flatMap()之后在问题中,它将提供之前单个计算的结果,我们忽略它。请注意,如果我们有 Flux<>相反,将对每个元素进行计算。

另一方面,then()不关心前面的事件顺序。它只关心完成事件:

enter image description here

这就是为什么,在您的示例中,使用哪一个并不重要。但是,在其他情况下您可能会做出相应的选择。

您可能还会找到Which operator do I need?项目 react 堆引用部分很有帮助。

关于java - 我应该使用 "then"还是 "flatMap"来控制流?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49710432/

相关文章:

java - 在 Joda 中将毫秒转换为日期时间格式时出现解析错误

java - 与父实体一起驱逐依赖集合

functional-programming - 什么是(函数式)响应式(Reactive)编程?

c# - 我们如何在 IObservable<T> 上使用组函数,同时观察未完成或在热的、长时间运行的可观察对象上

java - 如何拆分字符串而不丢失 Java 中的任何单词?

java - 使用 IntelliJ 对 hibernate 进行单元测试,如何设置 session 上下文?使用种子设置测试 mysql 数据库

error-handling - 第一个主机发生故障后,是否可以通过使用rxnetty来故障转移到辅助主机

java - 如何限制 Activity 的 Spring WebClient 调用次数

reactive-programming - WebFlux (Reactor) 中的文件处理

java - 将 Mono 的列表转换为 Flux