2017-09-26 41 views
0

下面的代碼工作:沒有得到完成事件上RxSwift與RxMoya

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

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中以下控制器使用startWith(())上加載啓動的內容。

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沒有被調用。我不知道爲什麼?請幫助我。

回答

0

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: [])