如何将List<Mono<Boolean>>顺序归约为单个Mono<Boolean>且遇false/异常终止?
问题分析
你需要顺序执行一组List<Mono<Boolean>>类型的任务,满足以下要求:
- 按列表顺序逐个执行任务
- 任意任务返回
false或抛出异常时,立即终止后续所有任务执行 - 所有任务执行成功返回
true;存在非异常失败返回false;出现异常直接透传错误
你之前用reduce实现的方案存在缺陷:reduce操作符需要等上游Flux的所有元素全部发射完成后才会执行聚合计算,无法提前向上游发送取消信号,因此即使中间出现false,Flux.concat还是会依次执行完所有任务,不符合提前终止的需求。
最优实现方案
直接使用Reactor内置的Flux.all()操作符即可完美匹配需求,代码非常简洁:
Mono<Boolean> process = Flux.concat(tasks) .all(Boolean::booleanValue);
特性匹配说明:
Flux.concat保证任务按列表顺序逐个订阅执行,只有前一个任务完成后才会触发下一个任务的订阅,天然满足顺序执行要求all(Boolean::booleanValue)的执行逻辑完全匹配终止和返回规则:- 只要遇到第一个返回
false的任务,会立即向上游发送取消信号,后续所有任务都不会被执行,最终返回的Mono<Boolean>结果为false - 所有任务都返回
true时,最终返回结果为true - 执行过程中任意任务抛出异常,会立即终止执行,直接把异常透传给下游
Mono
- 只要遇到第一个返回
用你给出的3个任务的示例测试这段代码,输出结果如下,符合task3不执行的预期:
Executing task 1... Finished executing task 1. Executing task 2... Finished executing task 2. false
可选自定义实现
如果你需要对返回false的场景做额外的自定义处理(比如打点日志),也可以用takeWhile配合last操作符实现,效果和all完全一致:
Mono<Boolean> process = Flux.concat(tasks) // 第二个参数true表示把不匹配的false元素也发射出来 .takeWhile(Boolean::booleanValue, true) // 取最后一个元素,即第一个false或者最后一个true .last();
内容的提问来源于stack exchange,提问作者Lukas S.
相关产品推荐
相关产品推荐

