Copybara bot | be50d49 | 2023-11-30 00:16:42 +0100 | [diff] [blame] | 1 | /** |
| 2 | * Since some events can fire at a high rate, the event handler should be limited to execute computationally |
| 3 | * expensive operations, such as DOM modifications, inside a single rendered frame. |
| 4 | * When listening to e.g. scroll and resize events, the browser tends to fire off more events per |
| 5 | * second than are actually useful. For instance, if your event listener sets some element positions, then it |
| 6 | * is possible for those positions to be updated multiple times in a single rendered frame. In this case, all of |
| 7 | * the layout calculations triggered by setting the elements' positions will be wasted except for the one time that |
| 8 | * it runs immediately prior to the browser rendering the updated layout to the screen. |
| 9 | * To avoid wasting cycles, we can use requestAnimationFrame to only run the event listener once just before the page |
| 10 | * is rendered to the screen. |
| 11 | * * |
| 12 | * @param callback the function to throttle |
| 13 | * @param context optional context of this, default to global |
| 14 | * @return {function(...[*])} |
| 15 | */ |
| 16 | const fullThrottle = (callback, context) => { |
| 17 | |
| 18 | if (!context) { |
| 19 | context = this || window; |
| 20 | } |
| 21 | |
| 22 | let throttling = false; |
| 23 | |
| 24 | return (...args) => { |
| 25 | if(!throttling) { |
| 26 | throttling = true; |
| 27 | window.requestAnimationFrame( () => { |
| 28 | throttling = false; |
| 29 | return Reflect.apply(callback, context, args); |
| 30 | }); |
| 31 | } |
| 32 | }; |
| 33 | }; |
| 34 | |
| 35 | export default fullThrottle; |