RxSwift - Debounce/Throttle "inverse"

RxSwift - Debounce/Throttle "inverse"

假设我有一个即时消息应用程序,每次收到消息时它都会发出哔声。我想 debounce 发出哔哔声,但我想在第一条消息到达时播放哔哔声,而不是为后续消息播放(在时间跨度内,比如 2 秒)。

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

这有意义吗?有运营商吗?现有运营商能否实现?

这是我的第一个例子的代码。我现在正在用 debounce 解决它,但它并不理想。如果我每隔 1 秒收到 1000 条消息,它不会在最后一条消息到达之前播放声音(我想在第一条消息上播放声音)。

self.messagesHandler.messages
            .asObservable()
            .skip(1)
            .debounce(2, scheduler: MainScheduler.instance)
            .subscribeNext { [weak self] message in
                    self?.playMessageArrivedSound()
            }.addDisposableTo(self.disposeBag)

谢谢!

针对 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 运算符,然后使用 flatMap.

Observable<Observable<Type>> 转换为平面 Observable

此示例代码仅在每 3 秒 windows 的第一次点击时打印 'tap'(或者如果点击次数超过 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)

Window 是一个很好的解决方案,但我发现示例运算符更直观且行为正确。

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

油门操作不符合我的预期。

对于同样觉得油门太混乱的人:

"throttle will only forward an event once the source observable has stopped sending events for the specified period of time. This does not work well with regular event delivery"for more details

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

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