RxSwift 将两个 api 请求合并为一个结果清除第一个结果

RxSwift merge two api request into one result clears first result

我有项目的 refreshTrigger 和 BehaviourRelay:

var refreshTrigger = PublishSubject<Void>()
var rootItems: BehaviorRelay<[Codable]> = BehaviorRelay(value: [])

然后,当用户输入文本时,我使用 UITextField 运行 搜索查询:

let queryText = queryTextField.rx.text.orEmpty
        .throttle(.milliseconds(300), scheduler: MainScheduler.instance)
        .distinctUntilChanged()

最后,我有一个 observable,它结合了这个 observable 和额外的触发器来手动刷新:

let refreshText = refreshTrigger.withLatestFrom(queryText)
Observable.merge(refreshText, queryText)
        .flatMapLatest { [weak self] query -> Observable<[Codable]> in
            guard let strongSelf = self else { return .empty() }
            
            let ctgs = try strongSelf.getCategories()
                .startWith([])
                .catchErrorJustReturn([])
            
            let itms = try strongSelf.getSearchResults(query)
                .retry(3)
                .startWith([])
                .catchErrorJustReturn([])
            
            return Observable.merge(ctgs, itms)
        }
        .bind(to: rootItems)
        .disposed(by: disposeBag)

如您所见,我想发送 2 个请求:获取类别和项目,因为我在同一个 UITableView 中显示它们。它同时发送两个请求,但是当第二个请求进来时第一个结果消失了。但是我使用合并,所以它应该可以工作。

为什么不显示合并结果?

Headers 的 getCategories 和 getSearchResults 看起来像这样:

func getSearchResults(_ text: String) throws -> Observable<[Codable]> 

func getCategories() throws -> Observable<[Codable]> 

他们都使用 alamofire 的 rx 扩展 运行 查询。

你的两个 getters return Observable 数组。这意味着当调用完成时,可观察对象会发出一个项目数组。当您 merge 两个 Observable 时,后续代码无法区分来自一个 getter 的项目和来自另一个 getter 的项目。它只是看到一个数组进入(来自其中一个),然后另一个数组进入(来自另一个)。换句话说,你误解了 merge 的工作原理。

要达到您想要的结果,您应该使用 zipcombineLatest 而不是 merge。像这样:

Observable.zip(ctgs, itms) { [=10=] +  }