You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Java中使用Mono实现响应式条件循环?

响应式管道中实现条件循环的正确方式

你的需求是在响应式管道里实现类似非响应式do-while的逻辑:先执行一次操作,然后判断条件,只要roundNumber < 超时时间且proof == null就继续循环,直到条件不满足时返回最终的proof,再执行后续处理。

原代码的问题

你尝试的代码存在两个核心问题:

  • doOnSuccess是副作用操作,它不会修改流中传递的数据。你在其中创建的Pair并没有被传递到后续的repeat操作符中,repeat拿到的其实是handleProofRequest返回的proof对象,导致条件判断完全失效。
  • 嵌套的flatMap结构错误,没有将roundNumber的判断结果和proof一起传递到下游,无法为循环提供正确的终止条件。

正确实现方式

方式一:递归调用(直观符合do-while逻辑)

将循环逻辑封装为递归方法,每次执行完单次尝试后判断是否需要继续循环:

// 封装单次尝试逻辑,返回当前的proof或继续递归
private Mono<String> attemptProofUntilCondition(Record record, Order order) {
    return handleDelayedRoundNumber()
            .flatMap(roundNumber -> handleProofRequest(record, order)
                    .flatMap(proof -> {
                        // 判断是否需要继续循环:round未超时且proof为空
                        boolean shouldContinue = roundNumber < order.clientMetadata().timeout() && proof == null;
                        if (shouldContinue) {
                            // 继续递归执行下一次尝试
                            return attemptProofUntilCondition(record, order);
                        } else {
                            // 终止循环,返回当前proof
                            return Mono.just(proof);
                        }
                    }));
}

// 调用逻辑
attemptProofUntilCondition(record, order)
        .flatMap(this::doStuffWithProof);

方式二:使用repeatWhenEmpty(响应式风格)

利用repeatWhenEmpty操作符,只有当需要继续循环时才重新订阅上游:

// 单次尝试,返回包含是否继续循环的标识和proof的Pair
private Mono<Pair<Boolean, String>> singleProofAttempt(Record record, Order order) {
    return handleDelayedRoundNumber()
            .flatMap(roundNumber -> handleProofRequest(record, order)
                    .map(proof -> {
                        boolean shouldRepeat = roundNumber < order.clientMetadata().timeout() && proof == null;
                        return new Pair<>(shouldRepeat, proof);
                    }));
}

// 调用逻辑
singleProofAttempt(record, order)
        // 只有当shouldRepeat为true时,才重复订阅上游
        .repeatWhenEmpty(flux -> flux.flatMap(pair -> pair.first() ? Mono.just(true) : Mono.empty()))
        // 取最后一次尝试的结果
        .last()
        // 提取proof
        .map(Pair::getSecond)
        .flatMap(this::doStuffWithProof);

非响应式逻辑对应说明

上述代码完全对应你给出的非响应式do-while逻辑:

Order order = ...;
Record record = ...;
String proof;
do {
   int roundNumber = handleDelayedRoundNumber();
   proof = handleProofRequest(record, order);
} while(roundNumber < order.clientMetadata().timeout() && proof == null);

doStuffWithProof(proof);

内容的提问来源于stack exchange,提问作者Marko Taht

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 12:27:42