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)
}
}
答案 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
:每当任何可观察序列产生一个元素时,将指定的可观察序列合并为一个可观察元组序列。
将两个不相关的事件结合在一起并做一些常见的事情真是太好了。
顺便说一句:我认为已经两天了,不知道如何解决。和我 系统地列出并发布在这里,过了一段时间,我想通了 出来。有趣的经历。