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

如何解决Mono.fromCompletionStage外部调用抛异常时错误算子不生效问题

问题根因与解决方案

根因分析

你遇到的问题本质是外部方法调用时机早于Mono实例创建,错误处理算子仅能捕获响应流生命周期内的异常,无法捕获Mono构建阶段抛出的异常:
你写的Mono.fromCompletionStage(externalCall(i))代码中,externalCall(i)是立即执行的,在flatMap收到元素后会先调用该方法,再用返回的CompletionStage构造Mono实例。如果调用externalCall直接抛出异常,此时Mono还未完成创建,挂载在它上面的doOnError、onErrorResume等算子根本没有生效的机会,异常会直接向上游抛出,最终被全局错误捕获器处理,就是你看到的ErrorCallbackNotImplemented日志。

解决方案

方案1:使用Mono.defer延迟执行(适配所有Reactor版本)

将externalCall的调用包裹在Mono.defer的Supplier函数中,将调用时机延迟到Mono被订阅时,此时抛出的异常会被Reactor自动纳入响应流错误处理链路:

private void example() {
    Flux.range(1, 2)
            .flatMap(i ->
                    // 用defer延迟externalCall的执行
                    Mono.defer(() -> Mono.fromCompletionStage(externalCall(i)))
                            .doOnNext(ni -> System.out.println("onNext: " + ni))
                            .doOnError(err -> System.err.println("onError: " + err.getMessage()))
                            .onErrorResume(e -> Mono.empty())
            )
            .subscribe();

    try {
        Thread.sleep(10000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

方案2:使用fromCompletionStageSupplier重载(Reactor 3.4.0及以上版本可用)

Reactor提供了接受Supplier参数的Mono.fromCompletionStage重载,会自动延迟CompletionStage的生成并捕获调用过程的异常,代码更简洁:

.flatMap(i ->
        // 直接传入Supplier,无需手动包裹defer
        Mono.fromCompletionStage(() -> externalCall(i))
                .doOnNext(ni -> System.out.println("onNext: " + ni))
                .doOnError(err -> System.err.println("onError: " + err.getMessage()))
                .onErrorResume(e -> Mono.empty())
)

效果说明

修改后externalCall抛出的异常会被错误处理算子正常捕获,onErrorResume返回Mono.empty后,当前元素会被忽略,流会继续处理后续的元素,满足你忽略异常继续执行的需求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 18:45:03