iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 14
0
Mobile Development

RxSwift / 30天探索之旅系列 第 14

第 14 天 - Combining Observables(中)

  • 分享至 

  • xImage
  •  

只放一天假後的禮拜一根本是大魔王...,今天繼續講Combining Observables

Concat

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

concatMapflatMap很像,相同之處在於一樣會將元素投影到一條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

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

從語意上了解,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
  1. 直得注意的是,onetwo的資料型態不同,combineLatest是少數可以合併不同資料型態的operator。
  2. 第一次Koala並沒有被發出來,因為這時的two尚未有元素,必須兩邊都有元素,combineLatest才會發出第一個合併的元素!如果有需要的話,可以搭配startWith() 給定預設值,讓combineLatest更早地發出元素。
  3. combineLatest後面接了一個closure,在裡面可以合併你想要的資料型態,你也可以不寫,結果就會像下面這樣,會直接以tuple方式合併
let result = Observable.combineLatest(one, two)

執行結果

("Koala", 2)
("Penguin", 2)
("Monkey", 2)
("Monkey", 7)

因為Combining Observables比較多,分了三天講,明天是最後一天了,就這樣,掰掰


上一篇
第 13 天 - Combining Observables(上)
下一篇
第 15 天 - Combining Observables(下)
系列文
RxSwift / 30天探索之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言