
Problem Statement
The task is to create a debounced version of a function. A debounced function is designed to increase the efficiency of handling frequently fired events by delaying the execution until a certain period (t
milliseconds) has lapsed. This is particularly useful in scenarios where a function should only proceed after a pause in activity. The effective result is that the function execution is postponed by t
milliseconds each time and is cancelled if a new call arrives within that postponement period.
For a precise scenario, if t = 50ms
, and function is triggered at timesteps 30ms
, 60ms
, and 100ms
, only the function call at 100ms
would proceed at 150ms
. This happens because the earlier calls at 30ms
and 60ms
are overridden by the subsequent calls that happen within the 50ms period from their respective initiation times.
Examples
Example 1
Input:
t = 50 calls = [ {"t": 50, inputs: [1]}, {"t": 75, inputs: [2]} ]
Output:
[{"t": 125, inputs: [2]}]
Explanation:
let start = Date.now(); function log(...inputs) { console.log([Date.now() - start, inputs ]) } const dlog = debounce(log, 50); setTimeout(() => dlog(1), 50); setTimeout(() => dlog(2), 75); The 1st call is cancelled by the 2nd call because the 2nd call occurred before 100ms The 2nd call is delayed by 50ms and executed at 125ms. The inputs were (2).
Example 2
Input:
t = 20 calls = [ {"t": 50, inputs: [1]}, {"t": 100, inputs: [2]} ]
Output:
[{"t": 70, inputs: [1]}, {"t": 120, inputs: [2]}]
Explanation:
The 1st call is delayed until 70ms. The inputs were (1). The 2nd call is delayed until 120ms. The inputs were (2).
Example 3
Input:
t = 150 calls = [ {"t": 50, inputs: [1, 2]}, {"t": 300, inputs: [3, 4]}, {"t": 300, inputs: [5, 6]} ]
Output:
[{"t": 200, inputs: [1,2]}, {"t": 450, inputs: [5, 6]}]
Explanation:
The 1st call is delayed by 150ms and ran at 200ms. The inputs were (1, 2). The 2nd call is cancelled by the 3rd call The 3rd call is delayed by 150ms and ran at 450ms. The inputs were (5, 6).
Constraints
0 <= t <= 1000
1 <= calls.length <= 10
0 <= calls[i].t <= 1000
0 <= calls[i].inputs.length <= 10
Approach and Intuition
Initial Setup:
- Define a wrapper function that incorporates timing logic to delay function execution based on the most recent call and
t
. - This function will keep track of the last call timing using a timeout.
- Define a wrapper function that incorporates timing logic to delay function execution based on the most recent call and
Handling Calls:
- Each time the debounced function is invoked, cancel the pending execution if any (using the timeout from the previous call), and schedule a new one.
- This is accomplished with
setTimeout
, setting it fort
milliseconds into the future.
Execution Conditions:
- If no new calls are made within
t
milliseconds from the last call, the function is executed with the parameters of the last issued call. - If a new call comes in during this window, reset the timer with the new call's parameters.
- If no new calls are made within
Example Walkthroughs:
- Example 1:
t = 50ms
- A call at
50ms
with input[1]
schedules an execution at100ms
. - Before this can occur, another call at
75ms
with[2]
comes in. The previous timer is cleared, and a new execution for[2]
is scheduled at125ms
. - Since no further calls occur before
125ms
,[2]
is executed at this time.
- A call at
- Example 2:
t = 20ms
- A function call at
50ms
results in execution at70ms
. - Another call at
100ms
results in a separate execution at120ms
.
- A function call at
- Example 3:
t = 150ms
- A function call at
50ms
with inputs[1, 2]
results in an execution at200ms
. - A call at
300ms
is superseded by another call at the same time (300ms
) but with different inputs[5, 6]
. - The call with inputs
[5, 6]
eventually gets executed at450ms
.
- A function call at
- Example 1:
This systematic postponement ensures that functions are not called too frequently in quick succession, potentially saving computation and enhancing performance especially in resource-intensive or I/O-bound operations.
Solutions
- JavaScript
var debounceFunction = function(func, delay) {
let timer;
return function(...arguments) {
const previous = Date.now();
clearInterval(timer);
timer = setInterval(() => {
if (Date.now() - previous >= delay) {
func(...arguments);
clearInterval(timer);
}
}, 1);
}
};
The code snippet provides a JavaScript implementation of the debounce technique. This pattern is especially useful in optimizing performance by limiting the rate at which a function can fire. For instance, it can be applied to events like scrolling, resizing, or keypresses in web development to reduce the number of event calls.
Here's a breakdown of how the provided debounce function works:
It accepts two parameters:
func
: The function you want to debounce.delay
: The minimum time interval (in milliseconds) that should elapse before the function is allowed to execute again.
Inside, a
timer
variable is declared usinglet
, ensuring it's only accessible within thedebounceFunction
's scope.The returned function captures any arguments passed to it using the JavaScript rest parameter syntax
...arguments
. This allows the function to accept and pass on an indefinite number of arguments tofunc
.Upon invoking the returned function, it clears any previous timeout set by
timer
to ensure it starts fresh.A new interval is set with
setInterval
. Inside its callback:- It checks if the current time minus the time of the previous call (
previous
) is greater than or equal to the specifieddelay
. - If true, it executes the function
func
with the originally provided arguments and clears the interval to prevent further execution.
- It checks if the current time minus the time of the previous call (
This implementation ensures that func
is not executed more frequently than the provided delay
. This pattern is beneficial for enhancing performance and reducing resource consumption in scenarios where functions might be called frequently and rapidly.
No comments yet.