-
Notifications
You must be signed in to change notification settings - Fork 295
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: rate limiting event listeners (debounce / throttle) #1298
Comments
I think this is exactly one of those cases I've found over the last 10-15 years that always has to be implemented somewhere in a UI, but requires a library or additional code to do. +1 for non-breaking additional properties that would add this support at the platform level for denouncing. Throttle and denounce are not the same IMHO so both could be valid. Denounce is the event handler on last event, but you could still slow down a UI without throttling. |
I find that this is most relevant when the handler itself will take time to execute, a variable amount of time, and there would be negative consequences of simultaneous execution of several instances of that asynchronous handler, e.g. an autocomplete input not ultimately displaying the final set of suggestions due to a race condition. As such, I think that the usefulness of this feature would be greatly increased if it detected promises returned by the handler and ensured that they reached resolution before allowing another invocation. |
@boutell I feel like edit this might have undesired side-effects around the |
See also webwewant.fyi/wants/4/ - judges pick and we did try to move that at some point iirc - I can't remember why it stalled |
I don't have any strong objection to an explicit option to turn on the behavior of always settling the previous promise before starting another invocation, although that this is a new API to start with so it could be reasonable to define its relationship to promises right from the start. If there's a super common case where this would be undesirable behavior I'd be interested to hear more about it. |
I think I'd prefer Either that, OR, if there needs to be a default duration, then: Rather than allowing Something like: {
debounce: true,
debounceDuration: 200,
throttle: true,
throttleDuration: 200,
} And the |
Would it be better to make it so that you can't set both? Something like...
Where I am not even proposing a name for this, but just a way to structure the arguments such that you don't both debounce and throttle? |
I like the thinking here, though we might also want to consider whether there's a precedent or whether we'd be introducing new API patterns (which might be warranted, but should be a conscious decision). Right now, I'm struggling to think of anything comparable within existing APIs, though that doesn't necessarily mean much... |
I'd prefer if these functions (throttle/debounce) were built-in to javascript. Limiting the eventListener call rate is useful but it's also limiting. Let's say for example i have two actions to perform when an event is triggered, one of them requires throttling and the other doesn't, that will force me to create 2 event listeners. |
+1 for built-in throttle and debounce functions independently from this proposal. |
It may be worth proposing these extensions as part of the Observables proposal which has the ability to add prototype methods, has a contract of variable timing (sync or async - therefore has good precedence for such operations), and is not strictly coupled to Events. |
@keithamus et al.: I don't disagree, but the original proposal quite intentionally limited its scope to the event context - in part because that seemed like a potential quick win1, but also for ergonomic reasons: Even if debouncing and throttling were available in some other form (via observables2, as stand-alone functions etc.), exposing such functionality via corresponding Footnotes
|
What problem are you trying to solve?
Developers often need to limit the frequency with which event handlers are being executed, both to improve performance and for behavioral reasons. Typically there are two distinct purposes, particularly when dealing with browser events fired in rapid succession: Debouncing delays the respective action until a steady state has been reached while throttling limits execution to once per time frame. (For details, see Debouncing and Throttling Explained Through Examples, perhaps also consult another visualization.)
Examples include avoiding excessive GUI updates, either for performance reasons (e.g. in response to resizing or scrolling) or to prevent flickering (e.g. when visualizing pointer coordinates or network-connection states), as well as reducing the frequency of network requests (e.g. auto-completion for keyboard inputs). A proposal from 2017 by @simevidas discusses additional use cases and considerations.
Providing a standardized approach for this common operation would enhance the web platform by reducing the need for custom implementations or third-party dependencies (in fact, it's not uncommon for an application to include multiple such implementations). In addition to browsers offering a reliable and efficient implementation, adding this capability to the platform would likely provide educational benefits by raising general awareness of debouncing and throttling.
What solutions exist today?
There are myriad JavaScript implementations for both debouncing and throttling, going back to at least 2009 with John Hann and Ben Alman. The concepts are also widely used in reactive programming; there might be parallel efforts within the context of the recent JavaScript proposals for observables and signals.
Presumably browser internals already include this functionality, without it being exposed to web developers.
How would you solve it?
Here we're primarily trying to address the issue of controlling browser events fired in rapid succession. Thus the obvious solution seems extending
addEventListener
with two new options:debounce
andthrottle
(complementingonce
).Note that a general-purpose solution for debouncing and throttling in JavaScript would exceed the scope of this particular proposal. (Though it's conceivable that might happen naturally in the future, if perhaps more through convention than via shared implementations.)
That leaves the question which values those options should assume:
debounce: true
andthrottle: true
would leave it up to browsers to decide a suitable delay, which might have performance and other contextual benefits (cf.requestAnimationFrame
). While such a default will often be just fine, sometimes developers will need more control.debounce: 200
andthrottle: 200
could specify a delay in milliseconds, much like withsetTimeout
, most likely addressing 90+ % of all use cases.My inclination is that supporting both boolean and numbers would be nice, but I'm not sure there's a precedent for that. It might also complicate documentation and education.
Anything else?
While I had considered creating a speculative polyfill, a future-proof implementation requires feature detection - that seems tricky for
addEventListener
options? In fact, support detection might need additional consideration before any such feature is introduced.I've belatedly realized #1070 already exists (thanks to domenic's issue transfer); is there a process for merging both issues?
The text was updated successfully, but these errors were encountered: