RxSwift - Debounce / Throttle" inverse"

时间:2016-02-16 16:47:06

标签: ios swift rx-swift

我们说我有一个即时通讯应用程序,每次收到消息时都会发出哔声。我希望debounce发出哔哔声,但是我想播放第一条消息的哔声,而不是下面的消息(在2秒的时间内)。

另一个例子可能是:我的应用程序发送了输入通知(因此我与之聊天的用户可以看到我正在键入消息)。我想在开始输入时发送打字通知,但只是以X秒的间隔发送新的通知,所以我不会为我输入的每个字符发送输入通知。

这有意义吗?那有运营商吗?可以通过现有的运营商来实现吗?

这是我的第一个例子的代码。我现在用self.messagesHandler.messages .asObservable() .skip(1) .debounce(2, scheduler: MainScheduler.instance) .subscribeNext { [weak self] message in self?.playMessageArrivedSound() }.addDisposableTo(self.disposeBag) 来解决它,但它并不理想。如果我以1秒的间隔收到1000条消息,它将不会播放声音,直到最后一条消息到达(我想在第一条消息上播放声音)。

$ sudo dd bs=4096 count=690 if=/dev/zero of=/mnt/tmp/test oflag=dsync
690+0 records in
690+0 records out
2826240 bytes (2,8 MB) copied, 29,2135 s, 96,7 kB/s

谢谢!

2 个答案:

答案 0 :(得分:21)

更新了RxSwift 3并改进了throttle运算符

使用RxSwift 3.0.0-beta.1中引入的throtlle运算符的新行为,您可以像这样使用它:

    downloadButton.rx.tap
    .throttle(3, latest: false, scheduler: MainScheduler.instance)
    .subscribe(onNext: { _ in
        NSLog("tap")
    }).addDisposableTo(bag)

旧版本的答案

使用window运算符,然后使用Observable<Observable<Type>>Observable转换为展平flatMap

此示例代码仅为每3秒窗口中的第一次点击打印“点击”(或者如果点击次数超过10000次)。

    downloadButton.rx_tap
    .window(timeSpan: 3, count: 10000, scheduler: MainScheduler.instance)
    .flatMap({ observable -> Observable<Void> in
        return observable.take(1)
    })
    .subscribeNext { _ in
        NSLog("tap")
    }.addDisposableTo(bag)

答案 1 :(得分:1)

窗口是一个很好的解决方案,但我发现样本操作符更直观,行为也更正确。

messagesHandler.messages
               .sample(Observable<Int>.timer(0.0, period: 2.0, scheduler: MainScheduler.instance))
               .subscribeNext { [weak self] message in
                    self?.playMessageArrivedSound()
               }.addDisposableTo(self.disposeBag)

油门操作不符合我的想法。

对于那些也发现油门过于混乱的人:

“一旦源观察者停止在指定的时间段内发送事件,”节流将仅转发事件。这对于常规事件传递“for more details不起作用。

在这种情况下,您想要的过滤器是

sample(Observable<Int>.timer(0.0, period: 2.0, scheduler: MainScheduler.instance))