Hi,
I'm new to Rx and wondered what is throttle is all about.
here is my code
locationManager.rx_didUpdateLocations
.throttle(2, MainScheduler.sharedInstance)
.debug()
.flatMap { location -> Observable<BaseResponseObject> in
self.mapView.camera = GMSCameraPosition(target: location.first!.coordinate, zoom: 15, bearing: 0, viewingAngle: 0)
return LocationTrackingRequest.sharedInstance.updateRequest(location.first!, endPoint: "location")
}
.retry()
.catchError { error in
print("ERROR")
return empty()
}
.subscribeNext { x in
print("Subscribe \(x)")
}
From what i read, it should fired the map every 2 seconds. But i waited it didn't call the rest chain. So i kind getting lost there. So what did it do and how to do it?
Throttle doesn't emit any events itself in that sense, it only forwards them, in this case the events emitted by rx_didUpdateLocations. However, it forwards only one event per given time, in this case two.
So if rx_didUpdateLocations doesn't emit any events, throttle doesn't forward any either.
Check out the this link to visualise it a little more.
Now I'm wondering however what the difference between debounce and throttle is :p
Yes, thank you.
After reread the documentation, i found this one.
It would be great if program would wait for some time before firing that request to server, after all, we > > don't want to spam our servers in case somebody is in the process of fast typing something very long. > Additional timer field maybe?
And after that, i achieved what i want with filter command.
from my understanding debounce will wait for the time given, and then send all that event at once. While throttle will wait until no event received and then forward them.
CMIIW
@suprie
Throttle and debounce are aliases for the same thing. :)
Thanks @larcus94 for the extremely short but neat explanation.
If you have similar questions, please consider joining the dedicate Slack channel.
Hmm, throttle does not do what I thought it did. Looks like this is a common complaint across Rx implementations, someone misnamed it early on & now we're stuck with it.
For people finding this issue: throttle will only forward an event once the source observable has stopped sending events for the specified period of time. This does not work well with regular event delivery; in the case of rx_didUpdateLocations, if you specify a duration longer than 1s, no location updates will ever be delivered. debounce is a much better name for this behaviour - IMO no-one should ever use throttle; it’s too confusing.
In this case, the filter you want is sample(Observable<Int>.timer(0.0, period: 2.0, scheduler: MainScheduler.instance))
FWIW I added a proposal for a new operator that handles that kind of situation, to be added to RxSwift+Ext: see description of the throttledSample operator, until we have a better name :)
@fipillet awesome! TBH though the sampling approach is STILL not the way a ‘proper’ throttle should work - if you have a long duration, you don’t get your initial event until the first sample, and there will be a delay introduced on the events that are delivered. Ideally:
Looks like ReactiveCocoa went through this a while ago and dropped the debounce style throttle in the Swift rewrite for the logic as described above. If it were up to me, I’d deprecate the existing throttle synonym - it can’t be easily replaced, but it could be removed.
@samritchie what you're asking for is exactly what I'm suggesting with throttledSample. Not sure I made it clear that the first event would immediately make it through, but this is the intent.
Also the issue with replacing throttle behavior is that RxSwift aims at compatibility with other Rx implementations, if only not to confuse people. I think keeping the current behavior, albeit flawed, is a good thing and creating a new operator that does the right thing is the way to go.
@fpillet the throttle that I was imagining wouldn’t require a scheduler - it would be pure filtering only. It’s possible dropping the 'last' events in a cluster would be unexpected, but I wouldn’t have thought so.
According to the doc linked above, the ONLY Rx implementation that uses throttle is Rx.NET - the rest all use debounce and/or something like throttleWithTimeout. Renaming to throttleWithTimeout would at least be less bad.
Hello, then, how Could I have a time that accumulates events and then send all of them instead of the last one?
Looks like we now have throttle(0.5, latest: false, scheduler: MainScheduler.instance) The latest boolean can be set to false if you don't wan't the last event to be fired
Most helpful comment
Looks like we now have
throttle(0.5, latest: false, scheduler: MainScheduler.instance)Thelatestboolean can be set to false if you don't wan't the last event to be fired