使用 RxMoya 在 RxSwift 上未获得 Completed 事件

Posted

技术标签:

【中文标题】使用 RxMoya 在 RxSwift 上未获得 Completed 事件【英文标题】:Not getting Completed event on RxSwift with RxMoya 【发布时间】:2017-09-26 09:01:44 【问题描述】:

以下代码有效:

    let provider = RxMoyaProvider<MyAPI>( stubClosure: MoyaProvider.delayedStub(3))

    provider
        .request(.studentSearch(query: ""))
        .retry(3)
        .observeOn(MainScheduler.instance)
        .asObservable()
        .mapJSON()
        .map  respJSON in
            guard let studentsJsonArray = JSON(respJSON)["students"].array else 
                throw APIError.wrongJSONParsing
            
            return studentsJsonArray.map 
                guard let students = Student.fromJSON($0) else 
                    fatalError("Invalid Student Object")
                
                return students
                 as [Student]
        
        .subscribe(onNext: 
          print($0)
        , onCompleted: 
          print($0) // This one is being called.
        )
        .disposed(by: rx.disposeBag)

上面的代码调用了onCompleted方法,下面的代码没有调用。

我正在尝试使用 UITableView 中的刷新触发器来刷新内容。我想在开始时加载内容,所以我在 ViewModel 的以下代码中使用startWith(())

let results: Driver<[Student]>
var refreshTrigger = PublishSubject<Void>()
results = refreshTrigger
        .startWith(())
        .do(onNext: 
            execute.value = true
        )
        .flatMapLatest 
            provider
                .request(.studentSearch(query: ""))
                .retry(3)
                .observeOn(MainScheduler.instance)
                .asObservable()
        
        .mapJSON()
        .map  respJSON in
            guard let studentsJsonArray = JSON(respJSON)["students"].array else 
                throw APIError.wrongJSONParsing
            
            return studentsJsonArray.map 
                guard let students = Student.fromJSON($0) else 
                    fatalError("Invalid Student Object")
                
                return students
            
        
        .do(onNext: 
            items.value = $0
            execute.value = false
            noResults.value = items.value.isEmpty
        , onCompleted: 
            print($0)
        )
        .asDriver(onErrorJustReturn: [])

在控制器中,我在 viewdidload 中调用。

viewModel
        .results
        .asObservable()
        .map  StudentGroup(header: "Follower", items: $0) 
        .subscribe(onNext: 
            print($0)
        , onCompleted: 
            print($0) // This is not being called.
        )
        .disposed(by: rx.disposeBag)

这里没有调用 onCompleted。不知道是什么原因?。请帮帮我。

【问题讨论】:

【参考方案1】:

flatMapLatest 不会发送 onCompleted 事件,除非其输入(在您的情况下为 PublishSubject)完成。 Moya 请求可以发送自己的 onCompleted 事件,但是当 flatMapLatest 合并结果时这些事件会被过滤掉。 换句话说,从 PublishSubject 到数据源的长期订阅未完成,也不应该完成。 (已编辑) (否则你会在第一次加载后失去刷新功能。)

我从 RxSwift Slack 频道的 Zsolt Varadi 那里得到了帮助。

解决办法

results = refreshTrigger
        .startWith(())
        .do(onNext: 
            execute.value = true
        )
        .flatMapLatest 
            provider
                .request(.studentSearch(query: ""))
                .retry(3)
                .observeOn(MainScheduler.instance)
                .asObservable()
                .mapJSON()
                .map  respJSON in
                    guard let studentsJsonArray = JSON(respJSON)["students"].array else 
                        throw APIError.wrongJSONParsing
                    
                    return studentsJsonArray.map 
                        guard let students = Student.fromJSON($0) else 
                            fatalError("Invalid Student Object")
                        
                        return students
                         as [Student]
                
                .map  StudentGroup(header: "Follower", items: $0) 
                .toArray()
                .catchErrorJustReturn([])
                .do(onNext: 
                    studentGroups.value = $0
                    execute.value = false
                    guard let isEmpty = studentGroups.value.first?.items.isEmpty else 
                        return
                    
                    noResults.value = isEmpty
                )
        
        .asDriver(onErrorJustReturn: [])

【讨论】:

以上是关于使用 RxMoya 在 RxSwift 上未获得 Completed 事件的主要内容,如果未能解决你的问题,请参考以下文章

在 RxMoya 中重复请求

使用 watchPosition 在 ios 设备上未获得准确的经纬度

使用 mvvm 模型的 RxMoya 请求总是在observer.onError(error) 中崩溃

如何正确过滤 RxMoya 中的SuccessfulStatusCodes

如何使用 RxSwift 和 alamofire 获得嵌套 api 调用的响应?

如何从 RxSwift 中的 onNext 获得正确的值?