doOnNext() vs flatMap():区别与适用场景

devtools/2025/3/4 23:57:51/

在 Reactor(Flux / Mono)中,doOnNext()flatMap() 都可以用来处理流中的元素,但它们有不同的作用和适用场景。


1. doOnNext()

✅ 作用
  • 用于执行副作用(side effects),但不会改变数据流
  • 适用于 日志记录、计数、打印信息、同步操作 等。
📌 特点
  • 不会改变数据流,只是对流中的元素 执行额外操作(如日志、统计等)。
  • 只适用于 同步操作不会等待异步任务完成
  • 返回 原始的 FluxMono,数据不会被修改。
🚀 示例
Flux<String> flux = Flux.just("A", "B", "C").doOnNext(item -> System.out.println("Processing: " + item)) // 仅执行副作用.map(String::toLowerCase); // 原始流不变flux.subscribe(System.out::println);
📝 输出
Processing: A
a
Processing: B
b
Processing: C
c

doOnNext() 只是执行副作用(打印日志),但不会修改流中的数据。


2. flatMap()

✅ 作用
  • 用于异步转换,可将一个元素映射为一个新的 MonoFlux(异步执行)。
  • 适用于 调用异步服务、数据库查询、Web 请求等
📌 特点
  • 返回 PublisherMonoFlux,会订阅并合并新的异步流。
  • 适用于 异步操作,如数据库查询、Web API 调用等。
  • 可以改变数据流A → Mono<B>)。
🚀 示例
Flux<String> flux = Flux.just("A", "B", "C").flatMap(item -> Mono.fromCallable(() -> {System.out.println("Processing: " + item);return item.toLowerCase(); // 返回 Mono<String>}));flux.subscribe(System.out::println);
📝 输出
Processing: A
a
Processing: B
b
Processing: C
c

flatMap() 会执行异步任务,并等待 Mono<String> 结果再继续。


3. doOnNext() vs flatMap() 的核心区别

对比点doOnNext()flatMap()
作用执行副作用(side effect),但不会改变数据流转换数据流,可返回新的 MonoFlux
适用于记录日志、计数、打印信息、同步操作异步操作(数据库查询、Web 请求等)
是否会改变流❌ 不改变流中的数据✅ 可以映射到新的数据流
是否支持异步❌ 只适用于同步操作✅ 适用于异步任务
是否订阅新的 MonoFlux❌ 不会订阅新的 Publisher✅ 会订阅新的 Publisher

4. 什么时候用 doOnNext(),什么时候用 flatMap()

doOnNext() 适用于

  • 只是想 观察数据流,但不改变数据:
    Flux.just("A", "B", "C").doOnNext(item -> log.info("Received: {}", item)).subscribe();
    
  • 记录日志、打印信息、计数等 副作用操作

flatMap() 适用于

  • 异步任务数据库查询、HTTP 请求等):
    Flux.just("user1", "user2").flatMap(userId -> getUserInfo(userId)) // 假设 getUserInfo 返回 Mono<User>.subscribe(user -> log.info("User: {}", user));
    
  • 需要等待异步任务的结果并修改数据流

5. 代码示例:WebSocket 处理

❌ 错误示例(doOnNext() 不能正确处理异步任务)

session.receive().doOnNext(message -> handleIncomingMessage(sessionId, message, missedPongs)) // handleIncomingMessage() 可能是异步的.then();

🚨 问题

  • handleIncomingMessage() 可能是一个异步任务(例如存数据库)。
  • doOnNext() 不会等待 Mono 任务完成,可能导致数据处理不完整。

✅ 正确示例(使用 flatMap() 处理异步任务)

session.receive().flatMap(message -> handleIncomingMessage(sessionId, message, missedPongs)) // 让 Reactor 订阅 `Mono`.then();

🔹 这样 handleIncomingMessage() 返回的 Mono<Void> 会被正确订阅,确保它的逻辑执行完成后才继续。


6. 结论

🚀 使用 doOnNext()

  • 适用于 日志、计数、打印等同步操作,不会改变数据流。
  • 不会订阅异步 MonoFlux

🚀 使用 flatMap()

  • 适用于 异步任务(数据库查询、API 调用等),确保 Reactor 正确订阅 Mono/Flux
  • 会等待异步任务完成,然后继续数据流。

📌 记住:如果 handleIncomingMessage() 可能是异步的(返回 Mono<Void>),你应该用 flatMap(),而不是 doOnNext() 🚀


http://www.ppmy.cn/devtools/164596.html

相关文章

解决Docker拉取镜像超时错误,docker: Error response from daemon:

当使用docker pull或docker run时遇到net/http: request canceled while waiting for connection的报错&#xff0c;说明Docker客户端在访问Docker Hub时出现网络连接问题。可以不用挂加速器也能解决&#xff0c;linux不好用clash。以下是经过验证的方法&#xff08;感谢轩辕镜…

Word快速替换修改学术论文所有中的中括号引用未上标格式

问题 如图是平时使用Word写完论文时候交叉引用的引用序号&#xff0c;由中括号和引用序号构成&#xff0c;如果不想手动修改使其上标&#xff0c;那么可以使用正则表达式来进行快速匹配替换使其上标&#xff0c;从而减少时间浪费&#xff0c;且能够保持交叉引用的跳转功能&…

陕西省地标-DB61/T 1121-2018 政务服务中心建设和运营规范

揭秘陕西省智慧政务服务中心新标准&#xff1a;打造高效便捷的服务新体验 随着信息化时代的深入发展&#xff0c;智慧政务已成为提升政府服务效率、优化营商环境的重要举措。陕西省作为全国政务改革的先行者&#xff0c;近期颁布了《陕西省地标-DB61_T 1121-2018 政务服务中心…

<el-cascader时只取最后一级数据

在用cascader时只取最后一级数据传给后端 组件的属性emitPath: false就可以做到&#xff0c;取值就是最后一级传给后端。并且后端放回的id 也直接可以做回显 <el-cascaderv-model"Type":options"Options":props"{ value: id, label: label, chil…

Java——通配符以及上下限

在 Java 泛型中&#xff0c;通配符 ? 用于表示未知类型&#xff0c;通常用于增强泛型的灵活性。通配符可以与 上限 和 下限 结合使用&#xff0c;进一步限制类型的范围。以下是通配符及其上下限的详细介绍&#xff1a; 一、通配符 ? 的基本用法 通配符 ? 表示未知类型&…

I2C总线详细介绍

目录 I2C 总线介绍1. I2C 的原理(1) 双线通信(2) 主从结构(3) 多设备通信(4) 硬件连接 2. I2C 的特性(1) 双向通信(2) 多主设备(3) 速度支持(4) 硬件简单(5) 地址区分 3. I2C 的协议(1) 起始条件&#xff08;Start Condition&#xff09;(2) 地址传输(3) 数据传输(4) 应答信号&…

Vue前端开发-Vant之Signature 组件

Signature组件用于页面的手写签名&#xff0c;它的功能基于Canvas实现&#xff0c;Vant版本必须大于或等于4.3.0才能使用该组件&#xff0c;当完成签名并触发绑定的submit事件后&#xff0c;在事件中&#xff0c;可以获取格式为base64字符串的签名图片&#xff0c;用于保存签名…

如何使用 preg_replace 处理复杂字符串替换

如何使用 preg_replace 处理复杂字符串替换 在 PHP 开发中&#xff0c;preg_replace 是处理正则表达式替换的核心函数&#xff0c;尤其适用于涉及模式匹配、动态替换和多规则处理的复杂场景。本文将通过实际案例和进阶技巧&#xff0c;解析如何高效利用该函数完成复杂字符串操…