RxSwfit 学习笔记(五)操作符,合并Observable序列,merge、combineLatest等

2,796 阅读3分钟

请各位务必要看这一篇,要不然后续的第六篇将会看得很难受。

顾名思义,合并Observable就是把多个Observable合并成一个。

那么废话不多说。开始吧

什么是操作符?

操作符可以帮助大家创建新的序列,或者变化组合原有的序列,从而生成一个新的序列。
RxSwfit 学习笔记(一)登录校验我们提到的案例中,我们有用到几个操作符map、combineLatest,这两个就是操作符。

在RxSwift中的操作符有非常多。

看看这图,就令人感觉头大。内容多,但是也只能一点一点的啃。

那今天我们就先了解一下转换操作符。

merge

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

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

摘录来自:RxSwift 中文文档。

案例

let disposeBag = DisposeBag()

let subject1 = PublishSubject<String>()
let subject2 = PublishSubject<String>()

Observable.of(subject1, subject2)
    .merge()
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)

subject1.onNext("🅰️")

subject1.onNext("🅱️")

subject2.onNext("①")

subject2.onNext("②")

subject1.onNext("🆎")

subject2.onNext("③"

打印结果

🅰️
🅱️
①
②
🆎
③

concat

让两个或多个 Observables按顺序串连起来

concat操作符将多个 Observables 按顺序串联起来,当前一个 Observable元素发送完毕后,后一个Observable 才可以开始发出元素。

concat将等待前一个 Observable产生完成事件后,才对后一个 Observable 进行订阅。如果后一个是“热” Observable,在它前一个Observable产生完成事件前,所产生的元素将不会被发送出来。

startWith 和它十分相似。但是startWith不是在后面添加元素,而是在前面插入元素。

merge和它也是十分相似。merge并不是将多个 Observables 按顺序串联起来,而是将他们合并到一起,不需要 Observables 按先后顺序发出元素。

concat与merge的区别 concat必须要前一个Observables发送onCompleted,才会发送后一个Observables发出来的元素。

案例

let disposeBag = DisposeBag()

let A = PublishSubject<String>()
let B = PublishSubject<String>()

Observable.of(A, B)
    .concat()
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)

A.onNext("A-1")

A.onNext("A-2")

B.onNext("B-1")

A.onCompleted()

B.onNext("B-2")

A.onNext("A-3")

B.onNext("B-3")

打印结果

A-1
A-2
B-2
B-3

zip

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

看着这一段的解释挺绕的,还是直接看案例会更快一点

经测试,zip就是会严格按照 一对一二对二的格式来。

案例

let disposeBag = DisposeBag()
let first = PublishSubject<String>()
let second = PublishSubject<String>()
let third = PublishSubject<String>()

Observable.zip(first, second,third) { $0 + $1 + $2}
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)

first.onNext("1")
second.onNext("A")
third.onNext("-test")
third.onNext("-test2")
third.onNext("-test3")
first.onNext("2")
second.onNext("B")
second.onNext("C")
second.onNext("D")
first.onNext("3")
first.onNext("4")

打印结果

1A-test
2B-test2
3C-test3

由输出结果我们可以看到,first跟second都发送了4个元素,而third只发了3个元素,那么打印出来的也只有3个。 我们可以理解成木桶效应,一旦有其中一个Observables发出的元素个数与其他Observables不对等,那么能打印出来的结果就只有最少的个数的元素。

combineLatest

多个 Observables 中任何一个发出一个元素,就发出一个元素。这个元素是由这些Observables中最新的元素,通过一个函数组合起来的

combineLatest操作符将多个Observables中最新的元素通过一个函数组合起来,然后将这个组合的结果发出来。这些源 Observables中任何一个发出一个元素,他都会发出一个元素(前提是,这些 Observables 曾经发出过元素)。

直接看案例更容易懂。 案例

let disposeBag = DisposeBag()

let first = PublishSubject<String>()
let second = PublishSubject<String>()

Observable.combineLatest(first, second) { $0 + $1 }
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)

first.onNext("1")
second.onNext("A")
first.onNext("2")
second.onNext("B")
second.onNext("C")
second.onNext("D")
first.onNext("3")
first.onNext("4")

打印结果

1A
2A
2B
2C
2D
3D
4D

RxSwfit 学习笔记(一)登录校验中,我们有用到combineLatest就是校验账号与密码的位数是否都超过5位,当两个校验都为true的时候,再让登录按钮enable。