A search box that asks the server at every key press sends three requests while you type "mug", and only the last answer matters. Debounce fixes that: it wraps a function so that it runs only once the calls have stopped for a while, with the arguments of the last call.
debounce(fn, ms) runs nothing by itself. It returns a new function, and the page calls that one instead of fn. Every call starts the wait again. When ms milliseconds pass with no new call, fn runs once.
The tools are timers. setTimeout runs a function later and returns an id, and clearTimeout with that id cancels it:
const id = setTimeout(() => console.log("Tea is ready"), 3000);
clearTimeout(id); // changed my mind: nothing prints
The check calls your function on its own fake clock and prints when fn ran. Among other cases, it must print:
search = debounce(fn, 300)
0 ms: search("m")
100 ms: search("mu")
200 ms: search("mug")
500 ms: fn("mug") runs
fn ran 1 time
save = debounce(fn, 300)
0 ms: save("draft 1")
299 ms: save("draft 2")
599 ms: fn("draft 2") runs
fn ran 1 time
field.changed = debounce(function, 200)
0 ms: field.changed("teapot")
200 ms: fn("teapot") runs, this.name is "Search"
Your task: in solution.js, write debounce(fn, ms). It returns a function that takes any arguments. Each call cancels the timer of the call before and starts a new one, which runs fn with the same this and the call's arguments.
Assignment
Follow the Coding Tutorial to write debounce: the function it returns, a shared timer, the setTimeout that runs fn, and the clearTimeout that starts the wait again.
Hint
Declare the timer in debounce, above the return, so every call of the returned function shares it. Cancel it before you start the new one.
Free plan: 30 tutor messages. PRO is unlimited.
