RxSwift - Debounce/Throttle "inverse"
Допустим, у меня есть приложение для обмена мгновенными сообщениями, которое воспроизводит звуковой сигнал каждый раз, когда приходит сообщение. я бы хотел debounce
звуковые сигналы, но я хотел бы воспроизвести звуковой сигнал для первого поступившего сообщения, а не для следующих (например, в течение 2 секунд).
Другой пример: мое приложение отправляет уведомления о наборе текста (чтобы пользователь, с которым я общаюсь, мог видеть, что я набираю сообщение). Я хочу отправить уведомление о наборе, когда я начну печатать, но отправлять новые только с интервалом в X секунд, поэтому я не отправляю уведомление о наборе для каждого набираемого символа.
Имеет ли это смысл? Есть ли оператор для этого? Может ли это быть достигнуто с существующими операторами?
Это мой код для первого примера. Я решаю это сейчас с debounce
, но это не идеально. Если я получу 1000 сообщений с интервалом в 1 секунду, он не будет воспроизводить звук до тех пор, пока не прибудет последнее сообщение (я хотел бы воспроизвести звук на первом).
self.messagesHandler.messages
.asObservable()
.skip(1)
.debounce(2, scheduler: MainScheduler.instance)
.subscribeNext { [weak self] message in
self?.playMessageArrivedSound()
}.addDisposableTo(self.disposeBag)
Спасибо!
2 ответа
Обновлен для RxSwift 3 и улучшен throttle
оператор
С новым поведением throtlle
оператор, представленный в RxSwift 3.0.0-beta.1, вы можете использовать его просто так:
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)
Окно - отличное решение, но я считаю, что пример оператора более интуитивен, а также с правильным поведением.
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 будет пересылать событие только после того, как наблюдаемый источник перестанет отправлять события в течение указанного периода времени. Это не очень хорошо работает с обычной доставкой событий" для более подробной информации.
В этом случае фильтр, который вы хотите
sample(Observable<Int>.timer(0.0, period: 2.0, scheduler: MainScheduler.instance))