I'm using a stream which is throttled when I scroll the window.
While throttling (as long as scrolling), it emits values to the console.
However , when stream is idle (user is not scrolling the window) - I want a timer to kick in. However - if the user starts scrolling again - I don't want that timer to emit values.
Currently I'm doing this :
const observable = Rx.Observable.fromEvent(window, 'scroll');
const subscriber = observable
.throttleTime(300 )
.map(() => 'throttle')
.merge(Rx.Observable.interval(1000).map(() => 'tick') )
.subscribe(
(x) => {
console.log('Next: event!', x);
},
(err) => {
console.log('Error: %s', err);
},
() => {
console.log('Completed');
});
The problem is that , while scrolling - I see both "throttle"
AND "tick"
( I should only see "throttle")
Think of this from another POV. A job always has to run. If I scroll - that throttled scroll - should invoke the job. If I don't scroll - a timer should kick in and start doing the job . (and stops if user start scrolling again).
Question:
How can I start a timer after an idle time of not scrolling ?
PLNKR
You can use debounceTime
to detect periods without scrolling.
const scroll = Rx.Observable.fromEvent(window, 'scroll')
.throttleTime(300)
.mapTo(false);
const noscroll = Rx.Observable.fromEvent(window, 'scroll')
.startWith(0) // init with no scroll.
.debounceTime(300) // detect no scroll after 300 ms.
.mapTo(true);
scroll.merge(noscroll)
.switchMap(e => e ? Rx.Observable.interval(1000).mapTo("Tick!") : Rx.Observable.of("Scroll!"))
// start the interval if there was no scroll. Stop the interval if there was a scroll.
.subscribe(updateTimer)
Another problem with your code is using merge
that will keep both sources subscribed, instead i use switchMap
(a sibling of mergeMap
) that will subscribe to the inner observable each time a new event is emitted, but also unsubscribe the previous inner source if another event is emitted from the source.
Re: "another POV" part of the question: You can replace Rx.Observable.interval(1000)
in switchMap
with the job. Scrolling will cancel/unsubscribe the job (as empty
is emitted), if there is no more scrolling, the job will start again.
Live demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With