【发布时间】:2019-04-28 03:45:42
【问题描述】:
RxSwift:如何摆脱订阅事件和网络请求的回调地狱?
我是一个新的 Swifter,这是我新公司的代码。
以下代码非常连贯。
逻辑很简单。 BoutiqueOutput 有一个 requestCommand,即 PublishSubject。它用于做一些刷新的事情(一次又一次地请求网络)。
回调地狱就在其中。网络层 Moya 以 RxSwift 的方式使用。
RxSwift 新手,我不知道如何很好地重构它。
如何正确使用filter/map/combine操作符?
这是用 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)
}
}
【问题讨论】: