合并可能返回Mono.empty()的多个Mono并聚合结果的技术实现问题
解决Reactor中Mono.zip因empty中断的聚合问题
这个问题我之前也碰到过——Mono.zip的行为确实容易让人踩坑,因为它严格要求所有源Mono都必须发射一个元素,只要有一个是Mono.empty(),整个zip流就会直接变成empty,根本走不到map那一步,自然拿不到你想要的聚合结果。
核心解决方案:将empty转换为null发射
要实现你想要的「即使某个Mono返回empty,也保留对应字段为null的聚合结果」,只需要给每个可能返回Mono.empty()的源Mono加上defaultIfEmpty(null)操作符,把empty状态转换成发射一个null值。这样每个Mono都会至少发射一个值(要么是原本的有效结果,要么是null),Mono.zip就能正常收集所有元素并完成聚合。
修改后的完整代码
fun main() { val mono1 = Mono.just(1) val mono2 = Mono.just("two") // 给empty的Mono加上defaultIfEmpty,将其转换为发射null val mono3 = Mono.empty<Boolean>().defaultIfEmpty(null) data class Aggregated( val f1: Int? = null, val f2: String? = null, val f3: Boolean? = null, ) Mono.zip(mono1, mono2, mono3) .map { tuple -> Aggregated(tuple.t1, tuple.t2, tuple.t3) } .subscribe( { c -> logger.info { c.toString() } }, // 输出:Aggregated(f1=1, f2=two, f3=null) { e -> logger.error(e) { e.message } }, { logger.info { ">> Done! " } } ) }
扩展:处理错误场景(可选)
如果你的Mono不仅可能返回empty,还可能抛出异常,想要把异常场景也对应到聚合字段的null,可以额外加上onErrorReturn(null)操作符:
// 同时处理empty和错误,统一返回null val mono3 = Mono.error<Boolean>(RuntimeException("Oops!")) .onErrorReturn(null) .defaultIfEmpty(null)
这样无论Mono是empty还是抛出错误,都会给zip流提供一个null值,保证整个聚合流程不会中断。
内容的提问来源于stack exchange,提问作者Jonathan Handoyo
相关产品推荐
相关产品推荐

