博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
RxSwift学习--高阶函数 / 操作符(上)
阅读量:4350 次
发布时间:2019-06-07

本文共 11797 字,大约阅读时间需要 39 分钟。

前言

RxSwift中,高阶函数也可以成为操作符,高阶函数可以帮助我们创建新的序列,或者变化组合原有的序列,从而生成一个新的序列。

转换操作符

1. map

map操作符会通过传入一个函数闭包把原来的 Observable 序列转变为一个新的 Observable 序列,map函数会将源序列的所有元素进行转换,返回一个新序列.

例子:

let disposeBag = DisposeBag()     Observable.of(1, 2, 3)        .map { $0 * 100}        .subscribe(onNext: { print($0) })        .disposed(by: disposeBag)        //结果:    100    200    300复制代码

2. flatMap

map在做转换的时候容易出现“升维”的情况。即转变之后,从一个序列变成了一个序列的序列。而flatMap 操作符会对源Observable 的每一个元素应用一个转换方法,将他们转换成 Observables。 然后将这些 Observables 的元素合并之后再发送出来。即又将其 降维成一个 Observable 序列。

这个操作符是非常有用的。比如当
Observable 的元素本身就拥有其他的
Observable 时,我们可以将所有子
Observables 的元素发送出来。

例子:

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)        //结果    1    3    2    5    6复制代码

3. flatMapLatest

flatMapLatest操作符会将Observable 的元素转换成其他的 Observable,然后取这些 Observables 中最新的一个。

flatMapLatest操作符将源
Observable 的每一个元素应用一个转换方法,将他们转换成
Observables。一旦转换出一个新的
Observable,就只发出它的元素,旧的
Observables 的元素将被忽略掉。

  • flatMapLatestflatMap 的唯一区别是:flatMapLatest 只会接收最新的 value 事件。
  • flatMapLatest实际上是mapswitchLatest操作符的组合
  • flatMapLatest就会有flatMapFirstflatMapFirstflatMapLatest正好相反:flatMapFirst 只会接收最初的 value 事件。(该操作符可以防止重复请求: 比如点击一个按钮发送一个请求,当该请求完成前,该按钮点击都不应该继续发送请求。便可该使用 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)            //结果:    1    3    2    5复制代码

4. concatMap

concatMap操作符会将 Observable的元素转换成其他的 Observable,然后将这些 Observables串连起来

concatMap操作符将源
Observable 的每一个元素应用一个转换方法,将他们转换成
Observables。然后让这些
Observables 按顺序的发出元素.

  • concatMapflatMap 的唯一区别是:当前一个 Observable 元素发送完毕后,后一个 Observable 才可以开始发出元素。等待前一个Observable 产生完成事件后,才对后一个 Observable 进行订阅。

例子:

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()        //结果:    1    3    6复制代码

5. scan

scan操作符会持续的将Observable ,然后发出每一次函数返回的结果

scan 操作符将对第一个元素应用一个函数,将结果作为第一个元素发出。然后,将结果作为参数填入到第二个元素的应用函数中,创建第二个元素。以此类推,直到遍历完全部的元素。也就是
scan 先给一个初始化的数,然后不断的拿前一个结果和最新的值进行处理操作。

例子:

let disposeBag = DisposeBag()    Observable.of(1, 2, 3, 4, 5)        .scan(0) { acum, elem in        acum + elem    }        .subscribe(onNext: { print($0) })        .disposed(by: disposeBag)    //结果    1    3    6    10    15复制代码

6. reduce

reduce操作符和scan操作符还是有点类似的,reduce 操作符将对第一个元素应用一个函数。然后,将结果作为参数填入到第二个元素的应用函数中。以此类推,直到遍历完全部的元素后发出最终结果。

例子:

let disposeBag = DisposeBag()    Observable.of(10, 20, 30)        .reduce(0, accumulator: +)        .subscribe(onNext: { print($0) })        .disposed(by: disposeBag)            //结果:    60复制代码

7.toArray

toArray操作符先把一个序列转成一个数组,并作为一个单一的事件发送,然后结束。

例子:

let disposeBag = DisposeBag()     Observable.of(1, 2, 3)        .toArray()        .subscribe(onNext: { print($0) })        .disposed(by: disposeBag)    //结果:    [1,2,3]复制代码

组合操作符

1. merge

merge操作符会将多个Observables 合并成一个Observable. 通过使用 merge 操作符可以将多个 Observables 合并成一个,当某一个 Observable 发出一个元素时,它就将这个元素发出。

如果,其中某一个
Observable 发出一个
onError 事件,那么被合并的 这个
Observable 也会将这个
onError 事件发出,并且立即终止序列。

值得注意的是这里被合并的序列元素必须是同类型的。

例子:

let disposeBag = DisposeBag()            let Henry = PublishSubject
() let Jeannie = PublishSubject
() 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) //结果: 1 2 100 3 4 1000 复制代码

2. startWith

startWith操作符会在 Observable 头部插入一些事件元素。即发出Observable的事件元素之前,会先发出这些预先插入的事件元素。

如果在
Observable头部分多次插入事件元素,那么这些事件元素会一直在
Observable头部追加,也就是后插入的先发出来。

例子:

let disposeBag = DisposeBag()            Observable.of("1", "2")        .startWith("A")        .startWith("B")        .startWith("a", "b")        .subscribe(onNext: { print($0) })        .disposed(by: disposeBag)        //结果:    a    b    B    A    1    2复制代码

3. zip

zip操作符可将多个 Observables 的元素组合压缩,而且它会等到每个Observable 元素事件一一对应地凑齐之后再合并,然后将每一个组合的结果元素发出来。

zip操作符最多可以将8个
Observables 的元素通过一个函数组合起来,然后将这个组合的结果发出来。它会严格的按照序列的索引数进行组合。例如,返回的
Observable的第一个元素,是由每一个源
Observables 的第一个元素组合出来的。它的第二个元素 ,是由每一个源
Observables 的第二个元素组合出来的。它的第三个元素 ,是由每一个源
Observables 的第三个元素组合出来的,以此类推。它的元素数量等于源
Observables中元素数量最少的那个。

例子:

let disposeBag = DisposeBag()    let Henry = PublishSubject
() let Jeannie = PublishSubject
() 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") //结果: 1A 2B 3C复制代码

zip操作符常常用在整合网络请求上。 比如我们想同时发送两个请求,只有当两个请求都成功后,再将两者的结果整合起来继续往下处理。这个功能就可以通过 zip 来实现。

4. combineLatest

combineLatest操作符同样是将多个Observables 序列元素进行合并。但与zip不同的是,每当任意一个 Observable有新的事件发出时,它会将每个Observable 序列的最新的一个事件元素进行合并,然后发送这个组合出来的元素。(前提是,这些 Observables 曾经发出过元素)。

例子:

let disposeBag = DisposeBag()    let Henry = PublishSubject
() let Jeannie = PublishSubject
() 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") //结果: 1A 2A 2B 2C 3C 4C复制代码

5. concat

concat 操作符将多个 Observables 按顺序串联起来,并且只有当前面一个 Observable 序列发出了 completed 事件,才会开始发送下一个 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)        //结果:    1    3    6    7复制代码

感觉concat操作符和concatMap操作符比较相似,它们都是要等到前面一个 Observable 序列发出了 completed 事件,才会开始发送下一个 Observable序列事件。

6. withLatestFrom

withLatestFrom操作符会将两个 Observables 最新的元素通过一个函数组合起来,当第一个 Observable 发出一个元素,就将组合后的元素发送出来。

例子:

let disposeBag = DisposeBag()    let firstSubject = PublishSubject
() let secondSubject = PublishSubject
() 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") //结果: B1复制代码

过滤条件操作符

1. filter

filter操作符就是用来过滤掉某些不符合要求的事件,仅仅发出Observable中通过判定的元素。

例子:

let disposeBag = DisposeBag()    Observable.of(11, 22, 3, 8, 2, 1)          .filter { $0 > 10 }          .subscribe(onNext: { print($0) })          .disposed(by: disposeBag)        //结果:    11    22复制代码

2. take

take操作符仅仅从 Observable中发出头n 个元素,在满足数量之后会自动发送 .completed事件。

例子:

let disposeBag = DisposeBag()    Observable.of(1, 2, 3, 4, 5, 6)        .take(3)        .subscribe(onNext: { print($0) })        .disposed(by: disposeBag)        //结果:    1    2    3复制代码

3. takeLast

takeLast操作符与take操作符类似,实现仅发送 Observable 序列中的后n个元素,忽略前面的元素。

例子:

let disposeBag = DisposeBag()    Observable.of(1, 2, 3, 4, 5, 6)        .takeLast(3)        .subscribe(onNext: { print($0) })        .disposed(by: disposeBag)        //结果:    4    5    6复制代码

4. takeWhile

takeWhile操作符会依次判断 Observable 序列的每一个值是否满足给定的条件。 当第一个不满足条件的值出现时,它便自动完成。

例子:

let disposeBag = DisposeBag()    Observable.of(2, 3, 4, 5, 6)       .takeWhile { $0 < 4 }       .subscribe(onNext: { print($0) })       .disposed(by: disposeBag)           //结果:    2    3复制代码

5. takeUntil

takeUntil操作符会忽略掉在第二个Observable 产生事件后发出的那部分元素。也就是,takeUntil 操作符会观测源Observable,它同时观测第二个 Observable。一旦第二个 Observable 发出一个元素或者产生一个终止事件,那么源Observable 将自动完成,停止发送事件。

例子:

let disposeBag = DisposeBag()            let Henry = PublishSubject
() let Jeannie = PublishSubject
() 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") //结果: next(Good) next(Lucky) completed复制代码

6. skip

skip操作符用于跳过源 Observable序列发出的前n 个元素事件。

例子:

let disposeBag = DisposeBag()     Observable.of(1, 2, 3, 4)        .skip(2)        .subscribe(onNext: { print($0) })        .disposed(by: disposeBag)            //结果:    3    4复制代码

7. skipWhile

skipWhile 操作符可以让你忽略源 Observable 中头几个满足条件的事件。

例子:

let disposeBag = DisposeBag()     Observable.of(2, 3, 4, 5, 6)        .skipWhile { $0 < 5 }        .subscribe(onNext: { print($0) })         .disposed(by: disposeBag)      //结果:   5   6复制代码

8. skipUntil

同上面的 takeUntil类似,skipUntil 除了订阅源 Observable外,通过 skipUntil 方法我们还可以监视另外一个 ObservableskipUntil操作符会跳过Observable 中头几个元素,直到另一个 Observable发出一个元素。

例子:

let disposeBag = DisposeBag()            let Henry = PublishSubject
() let Jeannie = PublishSubject
() 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) //结果: 3 4 5复制代码

9. elementAt

elementAt操作符只发出 Observable 中的第 n 个元素,即是只处理指定位置的元素事件

例子:

let disposeBag = DisposeBag()    Observable.of(1, 2, 3, 4)        .elementAt(2)        .subscribe(onNext: { print($0) })        .disposed(by: disposeBag)            //结果:    3复制代码

10. distinctUntilChanged

distinctUntilChanged操作符用于过滤掉连续重复的事件。如果后一个元素和前一个元素是相同的,那么这个元素将不会被发出来。如果后一个元素和前一个元素不相同,那么这个元素才会被发出来。

例子:

let disposeBag = DisposeBag()     Observable.of(1, 2, 1, 1, 1, 3)        .distinctUntilChanged()        .subscribe(onNext: { print($0) })        .disposed(by: disposeBag)        //结果    1    2    1    3复制代码

11.amb

amb操作符在多个源 Observables中, 取第一个发出元素或产生事件的 Observable,这个事件可以是一个 nexterror 或者 completed事件,然后就只发出这个Observable的元素事件,忽略掉其他的Observables

例子:

let disposeBag = DisposeBag()     let subject1 = PublishSubject
() let subject2 = PublishSubject
() let subject3 = PublishSubject
() 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) //结果: 1 2 3复制代码

总结

关于RxSwift的高阶函数先总结这么一部分。其实通过这些简单的示例来看,这些操作符在我们对序列进行操作的时候会有很大的帮助,而且使用简单。学好RxSwift,走遍天下都不怕。

感谢

转载于:https://juejin.im/post/5d4297495188255d4443bba7

你可能感兴趣的文章
使用Visual Studio 2013进行UI自动化测试
查看>>
13-集体照
查看>>
读了曾国藩家书,,心态逐渐平和起来。搞技术的如果缺乏信念的指引,生活会很乏味无聊!...
查看>>
前端javascript 错误 Uncaught SyntaxError: Unexpected token ILLEGAL
查看>>
2017.4.18 Java的Integer与int互转
查看>>
小程序接受返回数组的坑
查看>>
echart.js的使用
查看>>
自己动手写一个单链表
查看>>
生产者与消费者(综合案例)
查看>>
常用正则表达式
查看>>
6.2.7 Math对象的使用
查看>>
PHP 重置数组为连续数字索引的几种方式
查看>>
南阳理工acm 88-汉诺塔(一)
查看>>
160809308周子济第六次作业
查看>>
大型Web应用运行时 PHP负载均衡指南
查看>>
为phpStorm 配置PHP_CodeSniffer自动检查代码
查看>>
测试工具网址大全(转)
查看>>
ServiceStack DotNet Core前期准备
查看>>
webpack中‘vant’全局引入和按需引入【vue-cli】
查看>>
Date、String和Timestamp类型转换
查看>>