只放一天假後的禮拜一根本是大魔王...,今天繼續講Combining Observables
concat
是一個靜態的方法,給定一個排序過的Collection,先把第一個Sequence 元素都發送完,再發第二個Sequence,依此類推,直到全部Collection 都發送完畢,看起來就像把他們元素排列後串接起來,對吧?不過,值得注意的是,形態要是相同的才能Concat哦!
let first = Observable.of("A", "B", "C")
let second = Observable.of("D", "E", "F")
let concatObservable = Observable.concat([first, second])
concatObservable.debug("Concat").subscribe().disposed(by: disposeBag)
執行結果如下
Concat -> subscribed
Concat -> Event next(A)
Concat -> Event next(B)
Concat -> Event next(C)
Concat -> Event next(D)
Concat -> Event next(E)
Concat -> Event next(F)
Concat -> Event completed
Concat -> isDisposed
concatMap
跟flatMap
很像,相同之處在於一樣會將元素投影到一條Observable,然後最後合併結果在發出,但concat
的精髓就是順序,他會等第一條Observable發完並結束,才會進行第二元素投影到一條Observable ...,所以,最後結果一定會照順序發出的。
struct Zoo {
let animal: BehaviorSubject<String>
}
let zone1 = Zoo(animal: BehaviorSubject<String>(value: "Koala"))
let zone2 = Zoo(animal: BehaviorSubject<String>(value: "Lion"))
let subject = PublishSubject<Zoo>()
subject
.concatMap { $0.animal }
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
subject.onNext(zone1)
subject.onNext(zone2)
zone1.animal.onNext("Panda")
zone2.animal.onNext("Tiger")
zone1.animal.onCompleted()
zone2.animal.onNext("Cow")
執行結果
Koala
Panda
Tiger
Cow
merge
是很常用的一個語法,它可以將相同型態的Observable合併成一個Observable,接著只要收到元素它就發出去,比如說多條Observable ,各自代表不同情境,可能是按鈕點擊、下拉更新 ... 等狀況,這些情境都需要去trigger API,這時就可以把它們merge
起來,只要哪個情境觸發就可以 trigger API,大概會長這樣
let triggerAPI = Observable.merge(buttonTap, pullToRefresh)
triggerAPI.flatMapLatest { API().request().asObservable().materialize() }.share()
那下面展示簡單範例
let one = PublishSubject<String>()
let two = PublishSubject<String>()
let three = PublishSubject<String>()
let result = Observable.merge(one, two, three)
result
.subscribe(onNext: {
print("\($0)")
})
.disposed(by: disposeBag)
one.onNext("Koala")
two.onNext("Lion")
three.onNext(“Panda”)
執行結果
Koala
Lion
Panda
從語意上了解,combineLatest
是只會合併最新的元素,跟merge
一樣可以將多條Observable合併,不同的是它並不是收到元素就發送,而是結合最新的一起發送,先看看下面的範例
let one = PublishSubject<String>()
let two = PublishSubject<Int>()
let result = Observable.combineLatest(one, two) { str, number in
return "\(str), \(number)"
}
result
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
one.onNext("Koala")
two.onNext(2)
one.onNext("Penguin")
one.onNext("Monkey")
two.onNext(7)
執行結果如下
Koala, 2
Penguin, 2
Monkey, 2
Monkey, 7
one
跟two
的資料型態不同,combineLatest
是少數可以合併不同資料型態的operator。Koala
並沒有被發出來,因為這時的two
尚未有元素,必須兩邊都有元素,combineLatest
才會發出第一個合併的元素!如果有需要的話,可以搭配startWith() 給定預設值,讓combineLatest
更早地發出元素。combineLatest
後面接了一個closure,在裡面可以合併你想要的資料型態,你也可以不寫,結果就會像下面這樣,會直接以tuple方式合併let result = Observable.combineLatest(one, two)
執行結果
("Koala", 2)
("Penguin", 2)
("Monkey", 2)
("Monkey", 7)
因為Combining Observables比較多,分了三天講,明天是最後一天了,就這樣,掰掰