web-dev-qa-db-ja.com

RxSwift-デバウンス/スロットル「逆」

メッセージが届くたびにビープ音を鳴らすインスタントメッセージングアプリがあるとします。ビープ音を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)

ありがとう!

23
Bruno Koga

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<Observable<Type>>をフラット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)
24
Evgeny Sureev

ウィンドウは優れたソリューションですが、サンプルオペレーターの方が直感的であり、動作も適切です。

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

スロットル操作で思った通りに動きません。

スロットルもわかりにくいと感じる人にとっては:

「スロットルは、ソースオブザーバブルが指定された期間イベントの送信を停止した場合にのみイベントを転送します。これは、通常のイベント配信ではうまく機能しません。」 詳細について

この場合、必要なフィルターは

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