RxSwift高阶函数

352 阅读2分钟
Observable & Observer 既是可监听序列也是观察者

在我们所遇到的事物中,有一部分非常特别。它们既是可监听序列也是观察者。在Rx框架中定义了一些这样的辅助类型:AsyncSubject、ReplaySubject、BehaviorSubject、ControlProperty。

AsyncSubject:
//在序列产生完成事件后,发出最后一个元素(only one), 如果序列没有发出任何元素,那只有一个完成事件。如果产生了error事件而终止,那就不会发出任何元素,只发出一个error事件。
 let subject = AsyncSubject<String>()
        
        subject.subscribe { print("subscribe :", $0) }
            .disposed(by: disposeBag)
        
        subject.onNext("s1")
        subject.onNext("s2")
        subject.onCompleted()
        subject.onError(NSError.init(domain: "error", code: 404, userInfo: nil))       
 //输出结果
 subscribe : next(s2) 
 subscribe : completed
 
PublishSubject:
//只发送观察者订阅后的元素
let publish = PublishSubject<String>()
        publish.subscribe { print("subscribe1:", $0) }
            .disposed(by: disposeBag)
        
        publish.onNext("p1")
        publish.onNext("p2")
        
        publish.subscribe { print("subscribe2:", $0) }
            .disposed(by: disposeBag)
        
        publish.onNext("p3")
        publish.onNext("p4")           
        
//输出结果
 subscribe1: next(p1) subscribe1: next(p2) subscribe1: next(p3)
 subscribe2: next(p3) subscribe1: next(p4) subscribe2: next(p4)
 
ReplaySubject:
//会发送全部的元素  bufferSize:n  会发送订阅前的n个元素
        let replay = ReplaySubject<String>.create(bufferSize: 1)
        replay.subscribe { print("subscribe1:", $0) }
            .disposed(by: disposeBag)
        
        replay.onNext("r1")
        replay.onNext("r2")
        
        replay.subscribe { print("subscribe2 :", $0) }
            .disposed(by: disposeBag)
        
        replay.onNext("r3")
        replay.onNext("r4")
        
 //输出结果
subscribe1: next(r1)
subscribe1: next(r2)
subscribe2 : next(r2)
subscribe1: next(r3)
subscribe2 : next(r3)
subscribe1: next(r4)
subscribe2 : next(r4)
BehaviorSubject:
//当观察者订阅时,会发送最新的元素,如果没有新元素则发出默认元素,然后发送后续的元素(类似ReplaySubject<String>.create(bufferSize: 1))
        let behavior = BehaviorSubject(value: "b0")
        behavior.subscribe { print("subscribe1:", $0) }
            .disposed(by: disposeBag)
        
        behavior.onNext("b1")
        behavior.onNext("b2")
        
        behavior.subscribe { print("subscribe2:",$0) }
            .disposed(by: disposeBag)
        
        behavior.onNext("b3")
        behavior.onNext("b4")
 //输出结果
subscribe1: next(b0)
subscribe1: next(b1)
subscribe1: next(b2)
subscribe2: next(b2)
subscribe1: next(b3)
subscribe2: next(b3)
subscribe1: next(b4)
subscribe2: next(b4)
ControlProperty:
//用于描述UI属性,不会产生error事件,一定在主线程(MainSchedulder)订阅,共享附加作用(暂不明)
        let controlProperty = self.textFld.rx.text
        let observer = self.titleLab.rx.text
        controlProperty.bind(to: observer)
            .disposed(by: disposeBag)
操作符
// satrtWith: 指定序列的元素顺序 类似数组中插入第一个元素
        Observable.of("1", "2", "3")
            .startWith("a")
            .startWith("c")
            .startWith("e")
            .subscribe(onNext: {print($0)})
            .disposed(by: disposeBag)
        
        // merge: 将多个Observables 合并成一个,当其中一个序列发出一个元素时,新合并的序列就会将元素发出,如果有一个发出onError事件,合并序列就好终止
        let sub1 = PublishSubject<String>()
        let sub2 = PublishSubject<String>()
        
        Observable.of(sub1, sub2)
            .merge()
            .subscribe { print("merge:", $0) }
            .disposed(by: disposeBag)
        
        sub1.onNext("m1")
        sub2.onNext("m2")
        sub1.onNext("m3")
        sub1.onNext("m4")
        sub2.onNext("m5")
        sub2.onNext("m6")
        
        //zip: 通过函数将多个(最多8个)序列的元素组合并发出结果,按照序列的索引数进行组合。新序列的第一个元素是由每一个源序列的第一个元素组成,因此返回元素数量由最小(元素数量最少)的那个序列决定
        let z1 = PublishSubject<String>()
        let z2 = PublishSubject<String>()
        
        Observable.zip(z1, z2) {$0 + $1}
            .subscribe { print("zip:", $0) }
            .disposed(by: disposeBag)
        
        z1.onNext("z1")
        z1.onNext("z2")
        z1.onNext("z3")
        z2.onNext("z4")
        z2.onNext("z5")
        
        //combineLatest 和 zip类似  combineLatest会覆盖旧值
        let combine1 = PublishSubject<String>()
        let combine2 = PublishSubject<String>()

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

        combine1.onNext("1")
        combine2.onNext("A")
        combine1.onNext("2")
        combine2.onNext("B")
        combine2.onNext("C")
        combine2.onNext("D")
        combine1.onNext("3")
        combine1.onNext("4")
        
        //map: 将源序列的每个元素通过函数进行转换,返回一个转换结果的新序列
        Observable.of(1, 2, 3)
            .map{ $0 + 100 }
            .subscribe(onNext: {print("map:",$0)})
            .disposed(by: disposeBag)
        
        
        //flatMap: 当序列的元素本身拥有其他序列的时,可以将所有子序列的元素发送出来
        let flat1 = BehaviorSubject(value: "0")
        let flat2 = BehaviorSubject(value: "A")
        let flatSubject = BehaviorSubject(value: flat1)
        
        flatSubject.asObservable()
            .flatMap { $0 }
            .subscribe(onNext: { print("flatMap:",$0) })
            .disposed(by: disposeBag)
        
        flat1.onNext("1")
        flatSubject.onNext(flat2)
        flat2.onNext("B")
        
        //scan: 9 + 10 -> 19 + 100 -> 119 + 1000 = 1119 通过函数得到的结果作为参数进行下一次计算,每次结果都会作为新元素发送出来
        Observable.of(10, 100, 1000)
            .scan(9) { param, newValue in
                param + newValue
            }
            .subscribe(onNext: { print("scan:",$0) })
            .disposed(by: disposeBag)
        
        //filter: 过滤出符合条件的元素并发送出来
        Observable.of(1,2,3,4,5,6,7,8,9,0)
            .filter { $0 > 5 }
            .subscribe(onNext: { print("filter:",$0) })
            .disposed(by: disposeBag)
        
        //distinctUntilChanged: 相邻的元素相同则只会发送一个
        Observable.of("1", "2", "2", "2", "3", "3", "4", "5", "4")
            .distinctUntilChanged()
            .subscribe(onNext: { print("distinctUntilChanged:",$0) })
            .disposed(by: disposeBag)
        
        //elementAt: 发出序列中指定索引数的元素
        Observable.of("g", "l", "a", "c", "i", "e", "r")
            .element(at: 3)
            .subscribe(onNext: { print("elementAt:",$0) })
            .disposed(by: disposeBag)
        
        //single: 只发出序列发出的第一个元素(或满足条件的第一个元素)。如果序列没有元素或者元素数量大于一,将抛出一个错误。
        Observable.of("A", "B")
            .single()
            .subscribe(onNext: { print("single:",$0) })
            .disposed(by: disposeBag)
        
        Observable.of("C", "D")
            .single { $0 == "D" }
            .subscribe( onNext: { print("single2:",$0) } )
            .disposed(by: disposeBag)
        
        //take: 只从一个序列的开始发出指定数量的元素。 和signal相比,signal只能一个
        Observable.of("A", "B", "C", "D")
            .take(2)
            .subscribe(onNext: { print("take:",$0) })
            .disposed(by: disposeBag)
        
        //takeLast: 仅从序列的末尾发出指定数量的元素
        Observable.of("1", "2", "3", "4")
            .takeLast(3)
            .subscribe(onNext: { print("takeLast:",$0) })
            .disposed(by: disposeBag)
        
        //takeWhile: 只要指定条件的值为true,就从可观察序列的开始发出元素
        Observable.of(1, 2, 3, 4, 5, 6)
            .take(while: { $0 < 3 })
            .subscribe(onNext: { print("takeWhile:",$0) })
            .disposed(by: disposeBag)
        
        //takeUntil: 从源序列发出元素,直到参考序列发出元素。页面销毁了,就不能获取值了(cell重用运用)
        let sourceSequence = PublishSubject<String>()
        let referenceSequence = PublishSubject<String>()
        
        sourceSequence
            .take(until: referenceSequence)
            .subscribe(onNext: { print("takeUntil:",$0) })
            .disposed(by: disposeBag)
        
        sourceSequence.onNext("1")
        sourceSequence.onNext("2")
        sourceSequence.onNext("3")

        referenceSequence.onNext("Done") // 参考序列发出元素,原序列就不发送了
        
        sourceSequence.onNext("A")
        sourceSequence.onNext("B")
        sourceSequence.onNext("C")
        
        //toArray: 将一个序列转换为一个数组,将该数组作为一个新的单元素序列发出,然后终止
        Observable.range(start: 1, count: 10)
            .toArray()
            .subscribe{ print("toArray:",$0) }
            .disposed(by: disposeBag)
        
        //reduce: 从一个设置的初始化值开始,然后对一个序列发出的所有元素应用累加器闭包,并以单个元素序列的形式返回聚合结果 - 类似scan, 比较scan会发送所有的元素
        Observable.of(10, 100, 1000)
            .reduce(1, accumulator: +) // 1 + 10 + 100 + 1000 = 1111
            .subscribe(onNext: { print("reduce:",$0) })
            .disposed(by: disposeBag)
        
        //concat: 以顺序方式连接来自一个序列的内部序列的元素,在从下一个序列发出元素之前,等待每个序列成功终止
        // 用来控制顺序
        let subject1 = BehaviorSubject(value: "A")
        let subject2 = BehaviorSubject(value: "1")
        
        let concatSubject = BehaviorSubject(value: subject1)
        
        concatSubject.asObservable()
            .concat()
            .subscribe { print("concat:",$0) }
            .disposed(by: disposeBag)
        
        subject1.onNext("B")
        subject1.onNext("C")
        
        concatSubject.onNext(subject2)
        
        subject2.onNext("打印不出来")
        subject2.onNext("2")
        subject2.onNext("OK吗")
        
        subject1.onCompleted() // 必须要等subject1 完成了才能订阅到! 用来控制顺序 网络数据的异步
        subject2.onNext("3")