前言
在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
的元素将被忽略掉。
-
flatMapLatest
与flatMap
的唯一区别是:flatMapLatest
只会接收最新的value
事件。 -
flatMapLatest
实际上是map
和switchLatest
操作符的组合 - 有
flatMapLatest
就会有flatMapFirst
,flatMapFirst
与flatMapLatest
正好相反: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
按顺序的发出元素.
-
concatMap
与flatMap
的唯一区别是:当前一个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<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)
//结果:
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<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")
//结果:
1A
2B
3C
zip
操作符常常用在整合网络请求上。
比如我们想同时发送两个请求,只有当两个请求都成功后,再将两者的结果整合起来继续往下处理。这个功能就可以通过 zip
来实现。
4. combineLatest
combineLatest
操作符同样是将多个Observables
序列元素进行合并。但与zip
不同的是,每当任意一个 Observable
有新的事件发出时,它会将每个Observable
序列的最新的一个事件元素进行合并,然后发送这个组合出来的元素。(前提是,这些 Observables
曾经发出过元素)。
例子:
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")
//结果:
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<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")
//结果:
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<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")
//结果:
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
方法我们还可以监视另外一个 Observable
。skipUntil
操作符会跳过Observable
中头几个元素,直到另一个 Observable
发出一个元素。
例子:
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)
//结果:
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
,这个事件可以是一个 next
,error
或者 completed
事件,然后就只发出这个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)
//结果:
1
2
3
总结
关于RxSwift
的高阶函数先总结这么一部分。其实通过这些简单的示例来看,这些操作符在我们对序列进行操作的时候会有很大的帮助,而且使用简单。学好RxSwift
,走遍天下都不怕。
网友评论