RxSwift:如何摆脱订阅事件和网络请求的回调地狱?

时间:2019-04-28 03:45:43

标签: swift rx-swift

RxSwift:如何摆脱订阅事件和网络请求的回调地狱?

我是一名新的Swifter,这是我新公司的代码。

以下代码非常有线。

逻辑很简单。 BoutiqueOutput有一个requestCommand,即PublishSubject。它用于做一些刷新操作(再次请求网络初始化)。

回调地狱在其中。网络层Moya以RxSwift的方式使用。

RxSwift的新手,我不知道可以很好地重构它的模式。

如何以正确的方式使用过滤器/映射/合并运算符?

这是RxSwift封装的模型


import RxSwift
import RxCocoa
import RxDataSources
import MJRefresh
import Moya
import MoyaMapper


// this is the Moya Network Provider
let Provider = MoyaProvider<Router>(endpointClosure: EndpointClosure, requestClosure: requestClosure, plugins: [networkPlugin, MoyaMapperPlugin(NetParameter())], trackInflights: false)


struct BoutiqueOutput: OutputRefreshProtocol {

    var refreshStatus = Variable<RefreshStatus>(.none)

    let sections: Driver<[CategoryLeftSection]>

    let requestCommand = PublishSubject<Bool>()
    init(sections: Driver<[CategoryLeftSection]>) {
        self.sections = sections
    }
}


class CategoryViewModel: NSObject {

    let vmDatas = Variable<[ParentItem]>([])

    func transform() -> BoutiqueOutput {

        let tempSections = vmDatas.asObservable().map({ (sections) -> [CategoryLeftSection] in
            return [CategoryLeftSection(items: sections)]
        }).asDriver(onErrorJustReturn: [])

        let output = BoutiqueOutput(sections: tempSections)
        output.requestCommand.subscribe(onNext:{[weak self] _ in
            guard let self = self else { return }
            Provider.rx.cacheRequest(.baseUIData).subscribe( onNext:{ result in
                // do some UI 
                if result.statusCode == 200 || result.statusCode == 230 {
                    // do something business
                } 

            }).disposed(by: self.rx.disposeBag)
        }).disposed(by: rx.disposeBag)
        return output
    }
}


这是模型的应用方式

private var vmOutput: BoutiqueOutput?


override func viewDidLoad() {
        super.viewDidLoad()
        self.vmOutput = viewModel.transform()
        boundTableViewData()
    // ...
}


private func boundTableViewData() {

    let dataSource = RxTableViewSectionedReloadDataSource<CategoryLeftSection>( configureCell: { [weak self] ds, tv, ip, item in
     // ...
     }


  vmOutput!.sections.asDriver().drive(self.leftMenuTableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag)

     // ...

    vmOutput!.requestCommand.onNext(true)

}



private func requestErrorRefresh() {
     // ...
     if isNetworkConnect {
           boundTableViewData()
           vmOutput!.requestCommand.onNext(true)
     }
}


private func noNetworkRefresh() {
     // ...
     if isNetworkConnect {
           boundTableViewData()
           vmOutput!.requestCommand.onNext(true)
     }
}

1 个答案:

答案 0 :(得分:1)

我使用combineLatest运算符来解决此问题。

代码如下:

let output = BoutiqueOutput(sections: temp_sections)
Observable.combineLatest(output.requestCommand, Provider.rx.cacheRequest(.baseUIData)).subscribe({  [weak self]  ( result: Event<(Bool, Response)>) in
            guard let self = self else { return }
            switch result{
            case .next(let response):
                // do some UI 
                if result.statusCode == 200 || result.statusCode == 230 {
                     // do something business
                } 
            default:
                break
            }
        }).disposed(by: rx.disposeBag)    

combineLatest:每当任何可观察序列产生一个元素时,将指定的可观察序列合并为一个可观察元组序列。

将两个不相关的事件结合在一起并做一些常见的事情真是太好了。

  

顺便说一句:我认为已经两天了,不知道如何解决。和我   系统地列出并发布在这里,过了一段时间,我想通了   出来。有趣的经历。