Reputation: 153
I have an observable that throttles dragover
events by 350ms and returns true
as long as those events keep coming in:
Rx.Observable
.fromEvent(document, 'dragover')
.map(function () { return true; })
.throttle(350)
.distinctUntilChanged()
I want to know if there hasn't been a dragover event withinin the last 350ms and return false
when that happens. How should I go about doing that?
Do I need to have a separate timer and reset it whenever a dragover
event occurs? I'm hoping that I can keep this stateless.
Upvotes: 2
Views: 1226
Reputation: 18663
There is an operator called timeout
that does this.
Rx.Observable
.fromEvent(document, 'dragover')
.throttle(350)
.map(true)
.timeout(350, Rx.Observable.just(false))
.distinctUntilChanged();
A note that timeout
will unsubscribe from the source Observable
and subscribe with the one you passed in, so you won't get any further results from that Observable
until your resubscribe to it.
Also I would recommend that you put the map
operation after the throttle
in order to avoid unnecessary mapping operations of values you won't use.
And I would suggest thinking about if those timings are really what you want, since you are throttling over 350ms, timing out on 350ms leaves some pretty narrow margins. 1/3 of a second is not a lot of time to react especially for users. Since you already have a downstream distinctUntilChanged
you may not even need to throttle since you will only be emitting values when it goes from true to false.
Edit
If you need the Observable
to continue you can use doWhile
or repeat
to resubscribe (I used mousemove for my tests):
Rx.Observable.fromEvent(window, 'mousemove')
.map(true)
.timeout(1000, Rx.Observable.just(false))
.repeat()//.doWhile(function() { return true; })
.distinctUntilChanged()
.subscribe(function(value) { console.log(value); });
//Outputs
/* Mouse starts moving */
// true
/* Mouse stopped moving for 1 second */
// false
/* Mouse still not moving no emit */
/* Mouse starts moving again */
// true
Upvotes: 3
Reputation: 153
Ok, I think I ended up solving my own question. I removed the throttle operator. It was redundant because the browser throttles the dragover
event by 350ms anyway.
I created a source for dragover "start" events and a source for dragover "end" events. I gave both timestamps so that an end event's create time can be compared to a start event's create time:
var dragoverStart$ = Rx.Observable
.fromEvent(this.dom, 'dragover')
.timestamp()
.pluck('timestamp');
var dragoverEnd$ = dragoverStart$
.delay(350);
Rx.Observable
.combineLatest(dragoverStart$, dragoverEnd$)
.map(function (timestamps) {
return timestamps[0] > timestamps[1];
})
.distinctUntilChanged()
.subscribe(function (isDragging) {
// ...
});
Upvotes: 0