【问题标题】:RxSwift merge two api request into one result clears first resultRxSwift 将两个 api 请求合并为一个结果清除第一个结果
【发布时间】:2021-02-23 12:49:26
【问题描述】:

我有一个 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 中显示它们。它同时发送两个请求,但是当第二个请求进来时第一个结果消失了。但是我使用了合并,所以它应该可以工作。

为什么它不显示组合结果?

getCategories 和 getSearchResults 的标题如下所示:

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

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

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

【问题讨论】:

    标签: ios alamofire reactive-programming rx-swift


    【解决方案1】:

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

    要获得您想要的结果,您应该使用zip 或可能使用combineLatest 而不是merge。像这样的:

    Observable.zip(ctgs, itms) { $0 + $1 }
    

    【讨论】:

    • 就是这样!它正在工作。只是一个附带问题:在我的情况下,类别永远不会改变 - 它们总是相同的,但在当前的解决方案中,每次查询更改时都会加载项目和类别。是否可以在 flatMapLatest 之外加载类别,并在每次加载查询时将它们与项目合并?
    • 当然可以,但是您必须以不同的方式构造代码,这样您就不会在同一个闭包中发出两个网络请求。您可能还想引入 RxDataSources 或制作自定义数据源。写评论的代码太多了。问另一个问题或在 RxSwift slack 上提问rxslack.herokuapp.com
    猜你喜欢
    • 1970-01-01
    • 2013-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多