【发布时间】:2017-01-16 16:49:30
【问题描述】:
我目前在使用 RxSwift Observables 时遇到多个网络请求执行的问题。我知道,如果一个人创建了一个冷的 observable 并且它有多个观察者,那么 observable 将在每次订阅时执行它的块。
我尝试创建一个共享订阅 observable,它执行一次网络请求,多个订阅者将收到结果通知。以下是我尝试过的。
事件顺序
- 使用 uibutton 的点击事件创建视图模型
- 将 serviceStatus Observable 创建为视图模型上的公共属性。这个 Observable 是从 buttonTapped Observable 映射而来的。然后它会过滤掉“正在加载”状态。返回的 Observable 执行了 shareReplay(1) 以返回共享订阅。
- 创建 serviceExecuting Observable 作为视图模型上的公共属性。这个 observable 映射自 serviceStatus Observable。如果状态为“正在加载”,它将返回 true
- 将 uilabel 绑定到 serviceStatus Observable
- 将活动指示器绑定到 serviceExecuting Observable。
点击按钮时,服务请求会执行三次,而我预计它只会执行一次。有什么不正确的地方吗?
代码
class ViewController {
let disposeBag = DisposeBag()
var button: UIButton!
var resultLabel: UILabel!
var activityIndicator: UIActivityIndicator!
lazy var viewModel = { // 1
return ViewModel(buttonTapped: self.button.rx.tap.asObservable())
}
override func viewDidLoad() {
super.viewDidLoad()
self.viewModel.serviceStatus.bindTo(self.resultLabel.rx_text).addDispsoableTo(disposeBag) // 4
self.viewModel.serviceExecuting.bindTo(self.activityIndicator.rx_animating).addDispsoableTo(disposeBag) // 5
}
}
class ViewModel {
public var serviceStatus: Observable<String> { // 2
let serviceStatusObseravble = self.getServiceStatusObservable()
let filtered = serviceStatusObseravble.filter { status in
return status != "Loading"
}
return filtered
}
public var serviceExecuting: Observable<Bool> { // 3
return self.serviceStatus.map { status in
return status == "Loading"
}
.startWith(false)
}
private let buttonTapped: Observable<Void>
init(buttonTapped: Observable<Void>) {
self.buttonTapped = buttonTapped
}
private func getServiceStatusObservable() -> Observable<String> {
return self.buttonTapped.flatMap { _ -> Observable<String> in
return self.createServiceStatusObservable()
}
}
private func createServiceStatusObservable() -> Observable<String> {
return Observable.create({ (observer) -> Disposable in
someAsyncServiceRequest() { result }
observer.onNext(result)
})
return NopDisposable.instance
})
.startWith("Loading")
.shareReplay(1)
}
编辑:
根据下面的对话,我正在寻找以下内容......
我需要对 getServiceStatusObservable() 方法返回的 Observable 应用 share() 函数,而不是 createServiceStatusObservable() 方法返回的 Observable。有多个观察者被添加到这个 observable 来检查当前状态。这意味着执行网络请求的 observable 被执行了 N 次(N 是观察者的数量)。现在每次点击按钮时,网络请求都会执行一次,这正是我所需要的。
private func getServiceStatusObservable() -> Observable<String> {
return self.buttonTapped.flatMap { _ -> Observable<String> in
return self.createServiceStatusObservable()
}.share()
}
【问题讨论】: