我目前在使用RxSwift Observables時執行多個網絡請求時會出現問題。我明白,如果一個人創建了一個冷觀察者,並且它有多個觀察者,那麼觀察者將在每次訂閱時執行它的塊。RxSwift:防止多個網絡請求
我試圖創建一次執行網絡請求的共享訂閱observable,並將多個訂戶通知結果。以下是我所嘗試的。事件
- 的
序列與一個UIButton
- 的點擊事件創建視圖模型創建serviceStatus觀察爲上視圖模型公共財產。這個Observable從buttonTapped Observable映射而來。然後過濾掉「加載」狀態。返回的Observable在其上執行shareReplay(1)以返回共享訂閱。
- 在視圖模型上創建serviceExecuting Observable作爲公共屬性。這個可觀察值是從serviceStatus Observable映射而來的。如果狀態是「加載」
- 綁定的UILabel到serviceStatus可觀察
- 綁定活動的指標爲serviceExecuting可觀察到它會返回true。
當按鈕被點擊時,服務請求被執行三次,我期待它只被執行一次。有什麼事情脫穎而出嗎?
代碼
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,而不是從createServiceStatusObservable()方法返回的Observable。有多名觀察員被添加到這個觀察者來檢查當前狀態。這意味着執行網絡請求的observable被執行了N次(N是觀察者的數量)。現在每次點擊按鈕時,網絡請求都會執行一次,這正是我所需要的。
private func getServiceStatusObservable() -> Observable<String> {
return self.buttonTapped.flatMap { _ -> Observable<String> in
return self.createServiceStatusObservable()
}.share()
}
這是一個很好的地方,它看起來像解決了第一次點擊按鈕的問題。我更新shareReplay()to share(),因爲我不希望緩存結果,因爲用戶可以多次點擊該按鈕來執行新的服務請求。這是否意味着我應該對所有其他可觀察的事件做同樣的事情,因爲按鈕的後續點擊會導致對該服務的多個請求。 –
只要在第一次訂閱取消訂閱之前完成對其他觀察對象的訂閱,就可以僅在網絡請求上保留「共享」。 (在這種情況下,將執行新的請求)。 'share()'記錄在[這裏](https://github.com/ReactiveX/RxSwift/blob/3c55a309a24fbe3dbc480431798eec072b633b85/RxSwift/Observables/Observable%2BBinding.swift#L136)。 – tomahh
哎呀。我猜想我在這裏對getServiceStatusObservable()方法感到困惑。點擊按鈕時,已註冊的塊被調用三次。 {[weak self] _ - > Observable in return self.serviceStatusObservable } –