RxSwift 跳过事件直到自己的序列完成

Posted

技术标签:

【中文标题】RxSwift 跳过事件直到自己的序列完成【英文标题】:RxSwift Skip Events Until Own Sequence has finished 【发布时间】:2018-12-25 12:53:57 【问题描述】:

我有一个可以在短时间内发出多次的 observable(我们称之为触发器)。当它发出时,我正在执行网络请求,并且我正在使用扫描操作员存储结果。

我的问题是我想等到请求完成后再做一次。 (但现在如果触发器发出 2 个 observables,fetchData 是否完成并不重要,它会再次执行)

奖励:我也想每 X 秒只取第一个(Debounce 不是解决方案,因为它可以一直发射,我想每 X 秒获得 1 个,它也不是节流,因为如果observable 发射 2 倍真的快我会得到第一个和第二个延迟 X 秒)

代码:

trigger.flatMap  [unowned self] _ in
        self.fetchData()
        .scan([], accumulator:  lastValue, newValue in
        return lastValue + newValue
    )

和 fetchData:

func fetchData() -> Observable<[ReusableCellVMContainer]>

触发器:

let trigger = Observable.of(input.viewIsLoaded, handle(input.isNearBottomEdge)).merge() 

【问题讨论】:

【参考方案1】:

对不起,我误解了您在下面的回答中试图完成的任务。

将实现您想要的操作符是flatMapFirst。这将忽略来自触发器的事件,直到 fetchData() 完成。

trigger
    .flatMapFirst  [unowned self] _ in
        self.fetchData()
    
    .scan([], accumulator:  lastValue, newValue in
        return lastValue + newValue
    )

如果有帮助,我将在下面留下我之前的答案(如果有的话,它有“奖励”答案。)


您遇到的问题称为“背压”,即可观察对象产生值的速度比观察者处理的速度快。

在这种特殊情况下,我建议您不要限制数据获取请求,而是将每个请求映射到一个键,然后按顺序发出数组:

trigger
    .enumerated()
    .flatMap  [unowned self] count, _ in
        Observable.combineLatest(Observable.just(count), self.fetchData())
    
    .scan(into: [Int: Value](), accumulator:  lastValue, newValue in
        lastValue[newValue.0] = newValue.1
    )
    .map  $0.sorted(by:  $0.key < $1.key ).map  $0.value 

要完成上述工作,您需要:

extension ObservableType 
    func enumerated() -> Observable<(Int, E)> 
        let shared = share()
        let counter = shared.scan(0, accumulator:  prev, _ in return prev + 1 )
        return Observable.zip(counter, shared)
    

这样,您的网络请求会尽快开始,但您不会丢失它们发出的顺序。


对于您的“奖励”,buffer 运算符将完全满足您的需求。比如:

trigger.buffer(timeSpan: seconds, count: Int.max, scheduler: MainScheduler.instance)
    .map  $0.first 

【讨论】:

以上是关于RxSwift 跳过事件直到自己的序列完成的主要内容,如果未能解决你的问题,请参考以下文章

Rxswift 在事件发生时取消观察者并重新订阅

如何将 RxSwift 的 Single 转换为 Observable 并忽略“完成”事件?

RxSwift之深入解析Observable序列的创建

RxSwift - 将序列拆分为更小的序列以连接

RxSwift之常用的高阶函数

RxSwift 响应式编程详解(001)