嗨,今天把過去這幾天所講的Operator做個統整,並分享過去犯錯的範例,給大家借鏡借鏡。
相同之處
不同之處
merge
需要是相同型態,combineLatest
和zip
可以是不同型態merge
只要其中有一條Observable有發送元素,就成立,而combineLatest
和zip
則需要每一條都至少發送過一個元素後才成立使用時機
merge
:當需要統合多個resourcescombineLatest
:當resources只取最新的zip
:當resources需要一起出現相同之處
不同之處
combineLatest
可合併多個ObservablewithLatestFrom
是一個Observable為主,去取另一個Observable最新元素,共兩個使用時機
withLatestFrom
:當一個事件觸發時,去結合另一個resource自身錯誤範例
這是我翻很久之前跟學長對話的訊息發現的,剛好拿出來當作錯誤範例(笑)
情境大概像這樣,我想要點了按鈕去『取得』另一個Observable『最新』的資料,簡化後的程式大概像下面這樣
// 錯誤示範
let subject = PublishSubject<String>()
let resultObservable = Observable.combineLatest(button.rx.tap, subject)
resultObservable
.debug("Result")
.subscribe()
.disposed(by: disposeBag)
現在看起來,錯,錯的離譜,錯的荒唐,不過我當初確實這樣寫,這樣寫跟預期的結果有落差
((), "A")
((), "B")
這樣就不是我們想要的樣子了,一些情境下看起來正常,但在另一情境下就怪怪的,用錯operator就會這樣...,所以改成下面這樣
let resultObservable = button.rx.tap.withLatestFrom(subject)
就能確確實實以button.rx.tap
的事件去取得subject最新的元素。
跟上面的範例有點相似,在進行refresh時,希望它能取得目前選擇的item去call API,簡化後的程式大概像下面這樣
// 錯誤示範
let selectedItem = BehaviorRelay<String>(value: "Item A")
let refreshSubject = PublishSubject<Void>()
let resultObservable = refreshSubject.flatMapLatest { selectedItem }
resultObservable
.debug("Result")
.subscribe()
.disposed(by: disposeBag)
}
這樣會出什麼問題呢?
selectedItem.accept("Item B")
,也會使resultObservable發出元素,因為flatMapLatest特性,第一次Refresh時,就把元素投影到selectedItem
,並將結果合併到另一條Observable,也就是resultObservable,所以,當selectedItem持續發出元素,其結果都會到resultObservable所以還是要用withLatestFrom
,把他修改成
let resultObservable = refreshSubject.withLatestFrom(selectedItem)
到此為止,常用的operator都介紹完了,明天會介紹Error Handling Operators,就這樣,明天見。