RxSwift學(xué)習(xí)--高階函數(shù) / 操作符(上)

前言

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 的元素將被忽略掉。

  • flatMapLatestflatMap 的唯一區(qū)別是:flatMapLatest 只會(huì)接收最新的 value 事件。
  • flatMapLatest實(shí)際上是mapswitchLatest操作符的組合
  • flatMapLatest就會(huì)有flatMapFirst,flatMapFirstflatMapLatest正好相反: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ā)出元素.

  • concatMapflatMap 的唯一區(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ā)出。

image

如果,其中某一個(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,走遍天下都不怕。

感謝RxSwift中文文檔

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容