You need to enable JavaScript to run this app. RxSwift使用Observable.merge合并双API请求时首结果被清空的排查
优惠活动
大模型
产品
解决方案
定价
更多

RxSwift使用Observable.merge合并双API请求时首结果被清空的排查

问题根因

核心原因是对Observable.merge的行为存在认知错位,它的作用是按发射时间转发多个上游序列的所有事件,而非等待所有上游完成后把结果合并成一个整体,这是最终结果被覆盖的根源。
具体的事件流实际流转过程如下:

  • 代码中给ctgs、itms两个请求序列都加了startWith([])和错误兜底逻辑,两个序列被订阅时会立刻发射一个空数组,后续各自在接口返回时再发射对应的结果数组
  • merge作为转发管道,会把两个序列发射的每一个数组值,依次直接传给下游的rootItems绑定动作
  • 由于两个接口并行发起,谁的返回值先被merge转发,rootItems就会先更新为谁的数组;后返回的接口结果被merge再次转发时,会直接覆盖之前rootItems存储的旧值,自然不会出现两个数组合并的效果
    这套逻辑本质上是用事件转发的管道去实现“多请求结果聚合”的目标,方向本身就存在偏差。
符合预期的实现方式

如果要实现“并行发起两个接口请求,等两个请求都返回后,把分类数组和搜索结果数组拼接成一个完整列表再更新数据源”的目标,需要用适合做多请求结果聚合的操作符替代嵌套merge:

let refreshText = refreshTrigger.withLatestFrom(queryText)
Observable.merge(refreshText, queryText)
        .flatMapLatest { [weak self] query -> Observable<[Codable]> in
            guard let strongSelf = self else { return .empty() }
            
            // 分类请求:异常时兜底为空数组
            let categories = (try? strongSelf.getCategories())
                .flatMap { $0.catchErrorJustReturn([]) } ?? .just([])
            
            // 搜索请求:重试3次后异常兜底为空数组
            let searchResults = strongSelf.getSearchResults(query)
                .retry(3)
                .catchErrorJustReturn([])
            
            // 等两个请求都拿到有效结果后,拼接两个数组统一发射
            return Observable.zip(categories, searchResults)
                .map { $0 + $1 }
                .catchErrorJustReturn([])
        }
        .bind(to: rootItems)
        .disposed(by: disposeBag)
调整说明
  • 移除了两个请求序列上多余的startWith([]):这类操作会在请求尚未完成时就提前向下游发射空数组,造成不必要的列表闪烁和数据源临时覆盖
  • 用Observable.zip替代嵌套的merge:zip会等待两个上游序列都各自发射首个有效元素后,将两个值打包为元组统一触发一次下游发射,刚好匹配“两个请求并行、等全部返回后再聚合更新”的需求
  • 统一将错误兜底逻辑放在聚合完成的外层,避免中间值无序发射造成数据源被错误覆盖
  • 适配原方法的throws特性,把序列生成阶段的抛出异常做了兜底,避免因为方法本身抛错导致整个流中断

如果业务场景需要分阶段更新列表(比如分类接口先返回就先展示分类内容,搜索结果接口返回后再把结果追加到列表末尾),则不能直接将聚合后的数组流绑定到替换式的BehaviorRelay<[Codable]>,需要额外维护列表状态,将每次收到的分片数据累加到现有数组中,否则依然会出现覆盖问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.02 03:54:08