Given a function fn
and a time in milliseconds t
, return a debounced version of that function.
A debounced function is a function whose execution is delayed by t
milliseconds and whose execution is cancelled if it is called again within that window of time. The debounced function should also receive the passed parameters.
For example, let's say t = 50ms
, and the function was called at 30ms
, 60ms
, and 100ms
.
The first 2 function calls would be cancelled, and the 3rd function call would be executed at 150ms
.
Could you provide the code for the debounce function?
Here are some examples to test your code:
Example 1:
t = 50
calls = [
{"t": 50, inputs: [1]},
{"t": 75, inputs: [2]}
]
Expected Output:
[{t: 125, inputs: [2]}]
Example 2:
t = 20
calls = [
{"t": 50, inputs: [1]},
{"t": 100, inputs: [2]}
]
Expected Output:
[{t: 70, inputs: [1]}, {t: 120, inputs: [2]}]
Example 3:
t = 150
calls = [
{"t": 50, inputs: [1, 2]},
{"t": 300, inputs: [3, 4]},
{"t": 300, inputs: [5, 6]}
]
Expected Output:
[{t: 200, inputs: [1, 2]}, {t: 450, inputs: [5, 6]}]
This problem requires implementing a debounce function, which delays the execution of a given function until after a specified period of inactivity. This is useful for scenarios like handling rapidly-fired events (e.g., window resizing, typing in a search box) to avoid unnecessary computations.
A straightforward approach involves using setTimeout
to delay the execution of the function and clearTimeout
to cancel any pending executions if the debounced function is called again within the specified time window.
function debounce(fn, t) {
let timeoutId;
return function (...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
fn.apply(this, args);
}, t);
}
}
Explanation:
timeoutId
stores the ID of the timeout, allowing us to cancel it later.clearTimeout(timeoutId)
cancels any previously scheduled execution.setTimeout
schedules the execution of fn
after t
milliseconds.fn.apply(this, args)
calls the original function with the correct context (this
) and arguments.The naive approach is already quite efficient and serves as the optimal solution for this problem. The key is the proper use of setTimeout
and clearTimeout
to manage the delayed execution and cancellation of pending executions.
function debounce(fn, t) {
let timeoutId;
return function (...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
fn.apply(this, args);
}, t);
}
}
fn
is not considered part of the debounce function's complexity.timeoutId
.t
is 0, the function will be executed as soon as possible, but still asynchronously.fn
. You might want to add a try...catch
block if error handling is important.this
context: The apply
method ensures the correct this
context is passed to the debounced function.function debounce(fn, t) {
let timeoutId;
return function (...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
fn.apply(this, args);
}, t);
}
}