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

时间:2018-12-25 12:53:57

标签: swift rx-swift reactivex

我有一个可观察到的(我们将其称为触发器),可以在短时间内发出多次。当它发出信号时,我正在执行网络请求,并将结果存储在扫描操作员中。

我的问题是我想等到请求完成后再做一次。 (但是现在,如果触发器发出2个可观察值,则fetchData是否完成无关紧要,它将再次执行此操作)

奖金:我还想每X秒仅获取一次(防抖不是解决方案,因为它可以一直发射,我想每X秒获取1,这也不是限制,因为如果可观察到的发射速度真的快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 个答案:

答案 0 :(得分: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 }