Throttle with Trailing Edge in JavaScript
Throttling is a technique used to limit the rate at which a function can be executed. A throttle with a trailing edge ensures that the function is executed after a specified delay following the last call within a given window, allowing for a final execution even if calls cease. This is particularly useful for handling events like window resizing or scrolling, where you want to debounce updates but also ensure a final update after the user has finished interacting.
Problem Description
You are tasked with implementing a throttleWithTrailingEdge function in JavaScript. This function should take a callback function, a wait time (in milliseconds), and an optional leading edge flag (defaults to false) as arguments. The function should return a throttled version of the callback.
The throttled function should:
- Limit Execution: Ensure the callback function is not executed more frequently than the specified
waitTime. - Trailing Edge Execution: Execute the callback function after the
waitTimehas elapsed after the last call to the throttled function. - Leading Edge Option: If the
leadingEdgeflag is set totrue, execute the callback function on the leading edge of the wait time (immediately upon the first call within the window) in addition to the trailing edge. - Cancel Pending Execution: If the throttled function is called again before the trailing edge execution completes, cancel any pending trailing edge execution.
Expected Behavior:
- The throttled function should behave like a normal function initially.
- Subsequent calls within the
wait timeshould be ignored (except for leading edge if enabled). - After the
wait timefollowing the last call, the callback should be executed. - If the throttled function is called again before the trailing edge execution completes, the pending execution should be cancelled, and a new
wait timewindow should begin.
Examples
Example 1:
Input:
throttleWithTrailingEdge( () => console.log("Callback executed"), 1000 )
calls: throttledFunc(), throttledFunc(), throttledFunc() (all within 500ms)
Output:
(After 1000ms from the last call) "Callback executed"
Explanation: The first call triggers the throttle. The subsequent calls within 500ms are ignored. After 1000ms from the last call, the callback is executed.
Example 2:
Input:
throttleWithTrailingEdge( () => console.log("Callback executed"), 500, true )
calls: throttledFunc(), throttledFunc(), throttledFunc() (all within 250ms)
Output:
(Immediately) "Callback executed"
(After 500ms from the last call) "Callback executed"
Explanation: The leading edge flag is true, so the callback is executed immediately on the first call. Then, after 500ms from the last call, the callback is executed again (trailing edge).
Example 3:
Input:
throttleWithTrailingEdge( () => console.log("Callback executed"), 1000 )
calls: throttledFunc(), throttledFunc(), throttledFunc() (all within 500ms), throttledFunc() (after 1200ms)
Output:
(After 1000ms from the second call) "Callback executed"
(Immediately) "Callback executed"
Explanation: The first three calls are throttled. After 1000ms from the last of those calls, the callback is executed. The fourth call, occurring after 1200ms, triggers a new throttle window and executes the callback immediately.
Constraints
wait timewill be a positive integer (greater than 0).- The callback function can accept any number of arguments.
- The throttled function should maintain the
thiscontext of the original callback function. - The implementation should be efficient and avoid unnecessary memory usage.
- The function should handle edge cases gracefully, such as being called multiple times in rapid succession.
Notes
Consider using setTimeout or requestAnimationFrame to implement the trailing edge delay. Think about how to manage the pending execution and cancel it when necessary. The this context is important to preserve. Pay close attention to the leading edge behavior when it's enabled.