
前言
在RxSwift中,高階函數(shù)也可以成為操作符,高階函數(shù)可以幫助我們創(chuàng)建新的序列,或者變化組合原有的序列,從而生成一個(gè)新的序列。
轉(zhuǎn)換操作符
1. map
map操作符會(huì)通過(guò)傳入一個(gè)函數(shù)閉包把原來(lái)的 Observable 序列轉(zhuǎn)變?yōu)橐粋€(gè)新的 Observable 序列,map函數(shù)會(huì)將源序列的所有元素進(jìn)行轉(zhuǎn)換,返回一個(gè)新序列.
例子:
let disposeBag = DisposeBag()
Observable.of(1, 2, 3)
.map { $0 * 100}
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
//結(jié)果:
100
200
300
2. flatMap
map在做轉(zhuǎn)換的時(shí)候容易出現(xiàn)“升維”的情況。即轉(zhuǎn)變之后,從一個(gè)序列變成了一個(gè)序列的序列。而flatMap 操作符會(huì)對(duì)源Observable 的每一個(gè)元素應(yīng)用一個(gè)轉(zhuǎn)換方法,將他們轉(zhuǎn)換成 Observables。 然后將這些 Observables 的元素合并之后再發(fā)送出來(lái)。即又將其 降維成一個(gè) Observable 序列。
這個(gè)操作符是非常有用的。比如當(dāng)
Observable 的元素本身就擁有其他的 Observable 時(shí),我們可以將所有子 Observables 的元素發(fā)送出來(lái)。
例子:
let disposeBag = DisposeBag()
let Henry = BehaviorSubject(value: 1)
let Jeannie = BehaviorSubject(value: 2)
let Henry_Subject = BehaviorSubject(value: Henry)
Henry_Subject.asObservable()
.flatMap { $0 }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
Henry.onNext(3)
Henry_Subject.onNext(Jeannie)
Henry.onNext(5)
Jeannie.onNext(6)
//結(jié)果
1
3
2
5
6
3. flatMapLatest
flatMapLatest操作符會(huì)將Observable 的元素轉(zhuǎn)換成其他的 Observable,然后取這些 Observables 中最新的一個(gè)。
flatMapLatest操作符將源Observable 的每一個(gè)元素應(yīng)用一個(gè)轉(zhuǎn)換方法,將他們轉(zhuǎn)換成 Observables。一旦轉(zhuǎn)換出一個(gè)新的 Observable,就只發(fā)出它的元素,舊的 Observables 的元素將被忽略掉。
-
flatMapLatest與flatMap的唯一區(qū)別是:flatMapLatest只會(huì)接收最新的value事件。 -
flatMapLatest實(shí)際上是map和switchLatest操作符的組合 - 有
flatMapLatest就會(huì)有flatMapFirst,flatMapFirst與flatMapLatest正好相反:flatMapFirst只會(huì)接收最初的value事件。(該操作符可以防止重復(fù)請(qǐng)求:
比如點(diǎn)擊一個(gè)按鈕發(fā)送一個(gè)請(qǐng)求,當(dāng)該請(qǐng)求完成前,該按鈕點(diǎn)擊都不應(yīng)該繼續(xù)發(fā)送請(qǐng)求。便可該使用flatMapFirst操作符。)
例子:
let disposeBag = DisposeBag()
let Henry = BehaviorSubject(value: 1)
let Jeannie = BehaviorSubject(value: 2)
let Henry_Subject = BehaviorSubject(value: Henry)
Henry_Subject.asObservable()
.flatMapLatest{ $0 }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
Henry.onNext(3)
Henry_Subject.onNext(Jeannie)
Jeannie.onNext(5)
Henry.onNext(6)
//結(jié)果:
1
3
2
5
4. concatMap
concatMap操作符會(huì)將 Observable的元素轉(zhuǎn)換成其他的 Observable,然后將這些 Observables串連起來(lái)
concatMap操作符將源 Observable 的每一個(gè)元素應(yīng)用一個(gè)轉(zhuǎn)換方法,將他們轉(zhuǎn)換成 Observables。然后讓這些Observables 按順序的發(fā)出元素.
-
concatMap與flatMap的唯一區(qū)別是:當(dāng)前一個(gè)Observable元素發(fā)送完畢后,后一個(gè)Observable才可以開始發(fā)出元素。等待前一個(gè)Observable產(chǎn)生完成事件后,才對(duì)后一個(gè)Observable進(jìn)行訂閱。
例子:
let disposeBag = DisposeBag()
let Henry = BehaviorSubject(value: 1)
let Jeannie = BehaviorSubject(value: 2)
let Henry_Subject = BehaviorSubject(value: Henry)
Henry_Subject.asObservable()
.concatMap{ $0 }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
Henry.onNext(3)
Henry_Subject.onNext(Jeannie)
Jeannie.onNext(5)
Jeannie.onNext(6)
Henry.onCompleted()
//結(jié)果:
1
3
6
5. scan
scan操作符會(huì)持續(xù)的將Observable ,然后發(fā)出每一次函數(shù)返回的結(jié)果
scan 操作符將對(duì)第一個(gè)元素應(yīng)用一個(gè)函數(shù),將結(jié)果作為第一個(gè)元素發(fā)出。然后,將結(jié)果作為參數(shù)填入到第二個(gè)元素的應(yīng)用函數(shù)中,創(chuàng)建第二個(gè)元素。以此類推,直到遍歷完全部的元素。也就是scan 先給一個(gè)初始化的數(shù),然后不斷的拿前一個(gè)結(jié)果和最新的值進(jìn)行處理操作。
例子:
let disposeBag = DisposeBag()
Observable.of(1, 2, 3, 4, 5)
.scan(0) { acum, elem in
acum + elem
}
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
//結(jié)果
1
3
6
10
15
6. reduce
reduce操作符和scan操作符還是有點(diǎn)類似的,reduce 操作符將對(duì)第一個(gè)元素應(yīng)用一個(gè)函數(shù)。然后,將結(jié)果作為參數(shù)填入到第二個(gè)元素的應(yīng)用函數(shù)中。以此類推,直到遍歷完全部的元素后發(fā)出最終結(jié)果。
例子:
let disposeBag = DisposeBag()
Observable.of(10, 20, 30)
.reduce(0, accumulator: +)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
//結(jié)果:
60
7.toArray
toArray操作符先把一個(gè)序列轉(zhuǎn)成一個(gè)數(shù)組,并作為一個(gè)單一的事件發(fā)送,然后結(jié)束。
例子:
let disposeBag = DisposeBag()
Observable.of(1, 2, 3)
.toArray()
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
//結(jié)果:
[1,2,3]
組合操作符
1. merge
merge操作符會(huì)將多個(gè)Observables 合并成一個(gè)Observable.
通過(guò)使用 merge 操作符可以將多個(gè) Observables 合并成一個(gè),當(dāng)某一個(gè) Observable 發(fā)出一個(gè)元素時(shí),它就將這個(gè)元素發(fā)出。
如果,其中某一個(gè)
Observable 發(fā)出一個(gè) onError 事件,那么被合并的 這個(gè)Observable 也會(huì)將這個(gè)onError 事件發(fā)出,并且立即終止序列。
值得注意的是這里被合并的序列元素必須是同類型的。
例子:
let disposeBag = DisposeBag()
let Henry = PublishSubject<Int>()
let Jeannie = PublishSubject<Int>()
Observable.of(Henry, Jeannie)
.merge()
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
Henry.onNext(1)
Henry.onNext(2)
Jeannie.onNext(100)
Henry.onNext(3)
Henry.onNext(4)
Jeannie.onNext(1000)
//結(jié)果:
1
2
100
3
4
1000
2. startWith
startWith操作符會(huì)在 Observable 頭部插入一些事件元素。即發(fā)出Observable的事件元素之前,會(huì)先發(fā)出這些預(yù)先插入的事件元素。
如果在
Observable頭部分多次插入事件元素,那么這些事件元素會(huì)一直在Observable頭部追加,也就是后插入的先發(fā)出來(lái)。
例子:
let disposeBag = DisposeBag()
Observable.of("1", "2")
.startWith("A")
.startWith("B")
.startWith("a", "b")
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
//結(jié)果:
a
b
B
A
1
2
3. zip
zip操作符可將多個(gè) Observables 的元素組合壓縮,而且它會(huì)等到每個(gè)Observable 元素事件一一對(duì)應(yīng)地湊齊之后再合并,然后將每一個(gè)組合的結(jié)果元素發(fā)出來(lái)。
zip操作符最多可以將8個(gè)Observables 的元素通過(guò)一個(gè)函數(shù)組合起來(lái),然后將這個(gè)組合的結(jié)果發(fā)出來(lái)。它會(huì)嚴(yán)格的按照序列的索引數(shù)進(jìn)行組合。例如,返回的 Observable的第一個(gè)元素,是由每一個(gè)源 Observables 的第一個(gè)元素組合出來(lái)的。它的第二個(gè)元素 ,是由每一個(gè)源 Observables 的第二個(gè)元素組合出來(lái)的。它的第三個(gè)元素 ,是由每一個(gè)源 Observables 的第三個(gè)元素組合出來(lái)的,以此類推。它的元素?cái)?shù)量等于源 Observables中元素?cái)?shù)量最少的那個(gè)。
例子:
let disposeBag = DisposeBag()
let Henry = PublishSubject<String>()
let Jeannie = PublishSubject<String>()
Observable.zip(Henry, Jeannie) { $0 + $1 }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
Henry.onNext("1")
Jeannie.onNext("A")
Henry.onNext("2")
Jeannie.onNext("B")
Jeannie.onNext("C")
Henry.onNext("3")
Henry.onNext("4")
//結(jié)果:
1A
2B
3C
zip操作符常常用在整合網(wǎng)絡(luò)請(qǐng)求上。
比如我們想同時(shí)發(fā)送兩個(gè)請(qǐng)求,只有當(dāng)兩個(gè)請(qǐng)求都成功后,再將兩者的結(jié)果整合起來(lái)繼續(xù)往下處理。這個(gè)功能就可以通過(guò) zip 來(lái)實(shí)現(xiàn)。
4. combineLatest
combineLatest操作符同樣是將多個(gè)Observables 序列元素進(jìn)行合并。但與zip不同的是,每當(dāng)任意一個(gè) Observable有新的事件發(fā)出時(shí),它會(huì)將每個(gè)Observable 序列的最新的一個(gè)事件元素進(jìn)行合并,然后發(fā)送這個(gè)組合出來(lái)的元素。(前提是,這些 Observables 曾經(jīng)發(fā)出過(guò)元素)。
例子:
let disposeBag = DisposeBag()
let Henry = PublishSubject<String>()
let Jeannie = PublishSubject<String>()
Observable.combineLatest(Henry, Jeannie) { $0 + $1 }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
Henry.onNext("1")
Jeannie.onNext("A")
Henry.onNext("2")
Jeannie.onNext("B")
Jeannie.onNext("C")
Henry.onNext("3")
Henry.onNext("4")
//結(jié)果:
1A
2A
2B
2C
3C
4C
5. concat
concat 操作符將多個(gè) Observables 按順序串聯(lián)起來(lái),并且只有當(dāng)前面一個(gè) Observable 序列發(fā)出了 completed 事件,才會(huì)開始發(fā)送下一個(gè) Observable序列事件。
例子:
let disposeBag = DisposeBag()
let Henry = BehaviorSubject(value: 1)
let Jeannie = BehaviorSubject(value: 2)
let Henry_Subject = BehaviorSubject(value: Henry)
Henry_Subject.asObservable()
.concat()
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
Henry.onNext(3)
Henry_Subject.onNext(Jeannie)
Jeannie.onNext(5)
Jeannie.onNext(6)
Henry.onCompleted()
Jeannie.onNext(7)
//結(jié)果:
1
3
6
7
感覺concat操作符和concatMap操作符比較相似,它們都是要等到前面一個(gè) Observable 序列發(fā)出了 completed 事件,才會(huì)開始發(fā)送下一個(gè) Observable序列事件。
6. withLatestFrom
withLatestFrom操作符會(huì)將兩個(gè) Observables 最新的元素通過(guò)一個(gè)函數(shù)組合起來(lái),當(dāng)?shù)谝粋€(gè) Observable 發(fā)出一個(gè)元素,就將組合后的元素發(fā)送出來(lái)。
例子:
let disposeBag = DisposeBag()
let firstSubject = PublishSubject<String>()
let secondSubject = PublishSubject<String>()
firstSubject
.withLatestFrom(secondSubject) {
(first, second) in
return first + second
}
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
firstSubject.onNext("A?")
secondSubject.onNext("1")
firstSubject.onNext("B")
//結(jié)果:
B1
過(guò)濾條件操作符
1. filter
filter操作符就是用來(lái)過(guò)濾掉某些不符合要求的事件,僅僅發(fā)出Observable中通過(guò)判定的元素。
例子:
let disposeBag = DisposeBag()
Observable.of(11, 22, 3, 8, 2, 1)
.filter { $0 > 10 }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
//結(jié)果:
11
22
2. take
take操作符僅僅從 Observable中發(fā)出頭n 個(gè)元素,在滿足數(shù)量之后會(huì)自動(dòng)發(fā)送 .completed事件。
例子:
let disposeBag = DisposeBag()
Observable.of(1, 2, 3, 4, 5, 6)
.take(3)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
//結(jié)果:
1
2
3
3. takeLast
takeLast操作符與take操作符類似,實(shí)現(xiàn)僅發(fā)送 Observable 序列中的后n個(gè)元素,忽略前面的元素。
例子:
let disposeBag = DisposeBag()
Observable.of(1, 2, 3, 4, 5, 6)
.takeLast(3)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
//結(jié)果:
4
5
6
4. takeWhile
takeWhile操作符會(huì)依次判斷 Observable 序列的每一個(gè)值是否滿足給定的條件。 當(dāng)?shù)谝粋€(gè)不滿足條件的值出現(xiàn)時(shí),它便自動(dòng)完成。
例子:
let disposeBag = DisposeBag()
Observable.of(2, 3, 4, 5, 6)
.takeWhile { $0 < 4 }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
//結(jié)果:
2
3
5. takeUntil
takeUntil操作符會(huì)忽略掉在第二個(gè)Observable 產(chǎn)生事件后發(fā)出的那部分元素。也就是,takeUntil 操作符會(huì)觀測(cè)源Observable,它同時(shí)觀測(cè)第二個(gè) Observable。一旦第二個(gè) Observable 發(fā)出一個(gè)元素或者產(chǎn)生一個(gè)終止事件,那么源Observable 將自動(dòng)完成,停止發(fā)送事件。
例子:
let disposeBag = DisposeBag()
let Henry = PublishSubject<String>()
let Jeannie = PublishSubject<String>()
Henry
.takeUntil(Jeannie)
.subscribe { print($0) }
.disposed(by: disposeBag)
Henry.onNext("Good")
Henry.onNext("Lucky")
Jeannie.onNext("Bug")
Henry.onNext("Tnanks")
Henry.onNext("a lot")
//結(jié)果:
next(Good)
next(Lucky)
completed
6. skip
skip操作符用于跳過(guò)源 Observable序列發(fā)出的前n 個(gè)元素事件。
例子:
let disposeBag = DisposeBag()
Observable.of(1, 2, 3, 4)
.skip(2)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
//結(jié)果:
3
4
7. skipWhile
skipWhile 操作符可以讓你忽略源 Observable 中頭幾個(gè)滿足條件的事件。
例子:
let disposeBag = DisposeBag()
Observable.of(2, 3, 4, 5, 6)
.skipWhile { $0 < 5 }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
//結(jié)果:
5
6
8. skipUntil
同上面的 takeUntil類似,skipUntil 除了訂閱源 Observable外,通過(guò) skipUntil 方法我們還可以監(jiān)視另外一個(gè) Observable。skipUntil操作符會(huì)跳過(guò)Observable 中頭幾個(gè)元素,直到另一個(gè) Observable發(fā)出一個(gè)元素。
例子:
let disposeBag = DisposeBag()
let Henry = PublishSubject<Int>()
let Jeannie = PublishSubject<Int>()
Henry
.skipUntil(Jeannie)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
Henry.onNext(1)
Henry.onNext(2)
//開始接收消息
Jeannie.onNext(0)
Henry.onNext(3)
Henry.onNext(4)
//仍然接收消息
Jeannie.onNext(0)
Henry.onNext(5)
//結(jié)果:
3
4
5
9. elementAt
elementAt操作符只發(fā)出 Observable 中的第 n 個(gè)元素,即是只處理指定位置的元素事件
例子:
let disposeBag = DisposeBag()
Observable.of(1, 2, 3, 4)
.elementAt(2)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
//結(jié)果:
3
10. distinctUntilChanged
distinctUntilChanged操作符用于過(guò)濾掉連續(xù)重復(fù)的事件。如果后一個(gè)元素和前一個(gè)元素是相同的,那么這個(gè)元素將不會(huì)被發(fā)出來(lái)。如果后一個(gè)元素和前一個(gè)元素不相同,那么這個(gè)元素才會(huì)被發(fā)出來(lái)。
例子:
let disposeBag = DisposeBag()
Observable.of(1, 2, 1, 1, 1, 3)
.distinctUntilChanged()
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
//結(jié)果
1
2
1
3
11.amb
amb操作符在多個(gè)源 Observables中, 取第一個(gè)發(fā)出元素或產(chǎn)生事件的 Observable,這個(gè)事件可以是一個(gè) next,error 或者 completed事件,然后就只發(fā)出這個(gè)Observable的元素事件,忽略掉其他的Observables。
例子:
let disposeBag = DisposeBag()
let subject1 = PublishSubject<Int>()
let subject2 = PublishSubject<Int>()
let subject3 = PublishSubject<Int>()
subject1
.amb(subject2)
.amb(subject3)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
subject2.onNext(1)
subject1.onNext(20)
subject2.onNext(2)
subject1.onNext(40)
subject3.onNext(0)
subject2.onNext(3)
subject1.onNext(60)
subject3.onNext(0)
subject3.onNext(0)
//結(jié)果:
1
2
3
總結(jié)
關(guān)于RxSwift的高階函數(shù)先總結(jié)這么一部分。其實(shí)通過(guò)這些簡(jiǎn)單的示例來(lái)看,這些操作符在我們對(duì)序列進(jìn)行操作的時(shí)候會(huì)有很大的幫助,而且使用簡(jiǎn)單。學(xué)好RxSwift,走遍天下都不怕。