RxSwift 再来水一波, 某场景下,Sample 至于 withLatestFrom

738 阅读1分钟

Sample 至于 withLatestFrom,

场景是,控制器界面的一个按钮请求数据,另一个按钮调用最新的数据

( 因为按钮的点击时机不确定,就比较异步,很 Rx 响应式 )

这里区分出了主要的事件,辅助的事件 ( 来控制的 )

一个按钮请求数据,输入事件流,是事件仓库

另一个按钮调用最新的数据,控制事件流,决定前一个事件流的处理时机 ( 前一个事件流,只处理需要的,无用的事件抛弃 )

        let firstSubject = PublishSubject<String>()
        let secondSubject = PublishSubject<String>()
       
        
        firstSubject.sample(secondSubject).subscribe(onNext: { (memo) in
            print(memo)
        }).disposed(by: rx.disposeBag)
        
        
        firstSubject.onNext("1")
        
        secondSubject.onNext("A")
        firstSubject.onNext("2")
        secondSubject.onNext("B")
        secondSubject.onNext("C")
        firstSubject.onNext("3")
        firstSubject.onNext("4")
        secondSubject.onNext("D")
        firstSubject.onNext("5")

打印:

1 2 4


sample 升级一下,

一个事件流,是事件仓库

另外一个事件流,决定前一个事件流的处理时机 ( 前一个事件流,只处理需要的,无用的事件抛弃 )

处理前一个事件流的时候,也要用到第二个事件流的数据

这个时候,一般情况下可以用 withLatestFrom

    let firstSubject = PublishSubject<String>()
        let secondSubject = PublishSubject<String>()
       
        firstSubject.withLatestFrom(secondSubject){
                  (first, second) in
                  return first + second
             }
             .subscribe(onNext: { print($0) })
        .disposed(by: rx.disposeBag)

        firstSubject.onNext("1")
        
        secondSubject.onNext("A")
        firstSubject.onNext("2")
        secondSubject.onNext("B")
        secondSubject.onNext("C")
        secondSubject.onNext("D")
        firstSubject.onNext("3")
        firstSubject.onNext("4")
       
        firstSubject.onNext("5")

打印:

2A 3D 4D 5D


结一下:

  • 用 sample ,输入事件流,然后控制事件流

  • 用 withLatestFrom ,控制事件流,然后输入事件流

withLatestFrom , 可能会出现反复的采样sample ,

譬如例子结尾打印的

3D 4D 5D

  • 而 sample 则只采样一次,

第一个例子的

2

只打印一次

另一种拓展 Sample 的方式:

        let firstSubject = PublishSubject<String>()
        let secondSubject = PublishSubject<String>()

        Observable.zip(secondSubject.sample(firstSubject), firstSubject){
                  (first, second) in
                  return first + second
             }
             .subscribe(onNext: { print($0) })
        .disposed(by: rx.disposeBag)

        secondSubject.onNext("A")
        firstSubject.onNext("2")
        secondSubject.onNext("B")
        secondSubject.onNext("C")
        secondSubject.onNext("D")
        firstSubject.onNext("3")
        firstSubject.onNext("4")
       
        firstSubject.onNext("5")
        

打印:

A2 D3

这样标准了一些, 不会反复 sample ,

但需保证输入事件流 secondSubject 先走,再走控制事件流 firstSubject

secondSubject 之间,只能有一个 firstSubject,

还需保证 ...

(基于 zip 的特性 )


这样就不行了

        firstSubject.onNext("1")  // 这里
        
        secondSubject.onNext("A")
        firstSubject.onNext("2")
        secondSubject.onNext("B")
        secondSubject.onNext("C")
        secondSubject.onNext("D")
        firstSubject.onNext("3")
        firstSubject.onNext("4")
       
        firstSubject.onNext("5")

这也不行


         firstSubject.onNext("1")
        
        secondSubject.onNext("A")
        firstSubject.onNext("2")
        secondSubject.onNext("B")
        secondSubject.onNext("C")
        firstSubject.onNext("3")  // 这里
        firstSubject.onNext("4")  // 这里
        secondSubject.onNext("D")
        firstSubject.onNext("5")