问题
I think RxJS should perfectly fit to supress dublicate button clicks for 2 seconds. However, Im struggleing with the implementation.
var $button = $('#myButton').button();
$button
.toObservable("click")
//.Throttle(2000) // Wouldn't fire the first event instantly :-(
.Subscribe(function(){ alert('clicked'); });
I already created a jsFiddle for your convenience. You need to scroll down in this fiddle, because I just pasted Rx inside as I couldn't find a CDN.
http://jsfiddle.net/cburgdorf/mUMFA/2/
回答1:
I converted Sergeys answer into JavaScript and think this should be the final way to go.
var $button = $('#myButton').button();
$button
.toObservable("click")
.Take(1)
.Merge(Rx.Observable.Empty().Delay(2000))
.Repeat()
.Subscribe(function(){ console.log('clicked'); }
From my understanding this solutions is actually better because it doesn't rely on a sideeffect which makes it even better in terms of composability.
As Sergey pointed out, you could even go further and implement your own combinator like so:
Rx.Observable.prototype.OneInTime = function(delay){
return this
.Take(1)
.Merge(Rx.Observable.Empty().Delay(delay))
.Repeat();
};
So our example from above could be reduced to:
var $button = $('#myButton').button();
$button
.toObservable("click")
.OneInTime(2000)
.Subscribe(function(){ console.log('clicked'); });
回答2:
This is how I would do it in RxNet (sorry, I'm not familiar with RxJS so not sure if it is possible there):
public static IObservable<T> SupressDoubleClicks<T>(
this IObservable<T> source, TimeSpan delay)
{
return source
.Take(1)
.Merge(Observable.Empty<T>().Delay(delay))
.Repeat();
}
回答3:
Actually, Matthew from the Rx team was so kind to send me the answer via twitter: http://twitter.com/#!/mattpodwysocki/status/43731812513624064
So, what you can do is that:
var $button = $('#myButton').button();
$button
.toObservable("click")
.Do(function(){
alert('clicked');
$button.button('disable');
})
.Delay(2000)
.Do(function(){ $button.button('enable'); })
.Subscribe();
http://jsfiddle.net/cburgdorf/mUMFA/5/
However: For exercice reasons. I would prefer to make it work without setting enable/disable but just supressing the events for 2 seconds after the first occurence
In marble speech, Im looking for this:
O Stream: X---X---X---X---X---X---X
RxStream: X------------X------------X
回答4:
Crazy delicious!
I got it:
var $button = $('#myButton').button();
$button
.toObservable("click")
.Do(function(){ console.log('clicked'); })
.Take(1)
.Delay(2000)
.Repeat()
.Subscribe()
回答5:
I learned a lot from this thread and actually the crazy delicious iteration is by far the cleanest. But I wanted to return a compose-able event stream -- like in the converted Sergeys answer. So here's my method...
Rx.Observable.prototype.throttleOnFirst = function(ms){
var subject = new Rx.Subject();
var throttler = this
.do(function(data){subject.onNext(data)})
.take(1)
.delay(ms)
.repeat()
.subscribe()
return subject;
};
Mine is in angular so I use it like this...
var goToChaseTrigger = $scope.$createObservableFunction('goToChase');
var throttleAfterFirst = goToChaseTrigger
.throttleOnFirst(2000)
.subscribe(function(d){console.log('throttleOnFirst>',d)})
来源:https://stackoverflow.com/questions/5197032/how-to-take-first-occurrence-and-then-supress-events-for-2-seconds-rxjs