From 762cd9a10f5c92d5142566a741fcfea1d3351574 Mon Sep 17 00:00:00 2001 From: Shaban-Eissa Date: Mon, 27 May 2024 22:04:50 +0300 Subject: [PATCH] feat: implementation for debounce under the hood --- 6.implement-basic-debounce.md | 135 ++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 6.implement-basic-debounce.md diff --git a/6.implement-basic-debounce.md b/6.implement-basic-debounce.md new file mode 100644 index 0000000..ec2d8d1 --- /dev/null +++ b/6.implement-basic-debounce.md @@ -0,0 +1,135 @@ +# 6. implement basic debounce() + +What is debouncing? +Debouncing is a way of delaying the execution of a function until a certain amount of time has passed since the last time it was called. This can be useful for scenarios where we want to avoid unnecessary or repeated function calls that might be expensive or time-consuming. + + + +For example, imagine we have a search box that shows suggestions as the user types. If we call a function to fetch suggestions on every keystroke, we might end up making too many requests to the server, which can slow down the application and waste resources. Instead, we can use debouncing to wait until the user has stopped typing for a while before making the request. + +Here are three simple real life examples of debouncing: +- Submit button: When you click a submit button on a website, it doesn’t send the data immediately, but waits for a few milliseconds to see if you click it again. This way, it prevents accidental double submissions and errors. + +- Elevator: When you press the button to call the elevator, it doesn’t move immediately, but waits for a few seconds to see if anyone else wants to get on or off. This way, it avoids going up and down too frequently and saves energy and time. + +- Search box: When you type something in a search box, it doesn’t show suggestions on every keystroke, but waits until you stop typing for a while. This way, it avoids making too many requests to the server and improves the performance and user experience. + + +### Problem + +https://bigfrontend.dev/problem/implement-basic-debounce + +# + +### Problem Description + +Debounce is a common technique used in Web Application, in most cases using [lodash solution](https://lodash.com/docs/4.17.15#debounce) would be a good choice. + +could you implement your own version of basic `debounce()`? + +In case you forgot, `debounce(func, delay)` will returned a debounced function, which delays the invoke. + +Here is an example. + +Before debouncing we have a series of calling like + +─A─B─C─ ─D─ ─ ─ ─ ─ ─E─ ─F─G + +After debouncing at wait time of 3 dashes + +─ ─ ─ ─ ─ ─ ─ ─ D ─ ─ ─ ─ ─ ─ ─ ─ ─ G + +**notes** + +1. please follow above spec. the behavior might not be exactly the same as `lodash.debounce()` + +2. because `window.setTimeout` and `window.clearTimeout` are not accurate in browser environment, they are replaced to other implementation when judging your code. They still have the same interface, and internally keep track of the timing for testing purpose. + +Something like below will be used to do the test. + +```js +let currentTime = 0; + +const run = (input) => { + currentTime = 0; + const calls = []; + + const func = (arg) => { + calls.push(`${arg}@${currentTime}`); + }; + + const debounced = debounce(func, 3); + input.forEach((call) => { + const [arg, time] = call.split('@'); + setTimeout(() => debounced(arg), time); + }); + return calls; +}; + +expect(run(['A@0', 'B@2', 'C@3'])).toEqual(['C@5']); +``` + +# + +### Solution + +```js +/** + * @param {Function} func + * @param {number} wait + */ +function debounce(func, wait) { + let timer; + return function debounced(...args) { + if (timer) { + clearTimeout(timer); + } + timer = setTimeout(() => { + func.apply(null, args); + }, wait); + }; +} +``` + +# + +### Usage + +```js +const debounced = debounce(() => console.log("Hello World"), 1000); +debounced(); +debounced(); +debounced(); +debounced(); +debounced(); + +``` + +# + +### Explanation + +Let's break down the code: + +1. **Define the `debounce` function**: This function takes two parameters, `func` (the function to be debounced) and `wait` (the delay before `func` is allowed to be called again). It uses a variable, `timer`, to keep track of the delay timer. + +2. **Return the `debounced` function**: The `debounce` function returns a new function, `debounced`, which takes any number of arguments (`...args`). This function is a closure, meaning it has access to `func`, `wait`, and `timer` from the outer scope. + +3. **Clear the timer**: When `debounced` is called, it first checks if `timer` is not `null` (i.e., a timer is currently running). If it is, `debounced` clears the timer, cancelling the scheduled call to `func`. + +4. **Start a new timer**: `debounced` then starts a new timer that will last for `wait` milliseconds. When the timer ends, `func` is called with the provided arguments. + +In the usage example: + +1. **Create `debounced`**: The `debounce` function is called with a function that logs "Hello World" to the console and `1000` (1 second) as arguments. The returned debounced function is stored in `debounced`. + +2. **Call `debounced`**: `debounced` is called five times in quick succession. Due to the debouncing, the function passed to `debounce` is only called once, 1 second after the last call to `debounced`. This is because each call to `debounced` resets the timer, so the function is only called when `debounced` has not been called for 1 second. As a result, "Hello World" is logged to the console once, 1 second after the last call to `debounced`. + + +# + +### Reference + +- [The Difference Between Throttling and Debouncing](https://css-tricks.com/the-difference-between-throttling-and-debouncing/) +- [Debouncing and Throttling Explained Through Examples](https://css-tricks.com/debouncing-throttling-explained-examples/) +- [JavaScript Debounce Function](https://davidwalsh.name/javascript-debounce-function)