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

Spring Webflux:返回响应前等待所有Flux<T>完成

问题分析

你当前代码的核心问题是手动调用subscribe()并同步返回集合,完全违背了Reactor异步非阻塞的设计逻辑:

  • forEach里的subscribe()会触发异步插入,但不会等待这些操作完成
  • 外层的map是同步操作,会立刻返回空的buf(或仅填充少量已完成的插入结果),导致控制器提前响应,后续未完成的插入操作被直接终止
解决方案

重构Service层代码,用Reactor原生操作符正确编排异步流,确保所有插入操作完成后再返回结果:

修正后的Service代码

public Mono<List<Foo>> addFoos() {
    return webClient.getSomeStuff()
            // 将获取到的结果集合转为Flux,实现逐个异步处理
            .flatMapMany(results -> Flux.fromIterable(
                    results.stream()
                            .map(/* ...transform to domain model */)
                            .toList()
            ))
            // 并行处理每个Foo的插入(如需串行执行,替换为concatMap)
            .flatMap(foo -> fooDao.createFoo(foo))
            // 等待所有插入操作完成,收集结果为List后返回
            .collectList();
}

DAO代码优化(可选但更符合语义)

插入单条数据应该返回单个结果,建议把createFoo的返回类型从Flux<Foo>改为Mono<Foo>:

public Mono<Foo> createFoo(final Foo foo) {
    var query = "<INSERT_STUFF_STATEMENT>";

    var connection = Mono.from(publisher);
    return connection.flatMap(c -> c.createStatement(query)
            .bind("STUFF", foo.getStuff())
            .execute())
            // 取插入操作的第一个结果(单条插入仅会有一个结果)
            .next()
            .map(result -> Foo.builder()
                    .stuff(whatever)
                    .build());
}
关键逻辑说明
  • flatMapMany:将获取到的集合转为Flux,让每个元素都能进入异步处理流
  • flatMap/concatMap:处理单个Foo的插入操作,flatMap默认并行执行,concatMap保证串行执行
  • collectList:等待Flux中所有元素处理完成,收集为List后包装成Mono返回,确保控制器在所有插入完成后才响应

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 21:18:33