If a function is called multiple times, then if it is debounced then it will wait for specified time and then execute the last call.
In other words if a function is debounced for 1000ms then after multiple calls, if there exists time lag of greater than 1000ms then only the function will get executed, else it will not
OR in other words, execute this function only if 100 milliseconds have passed without it being called
Uses:
while typing text to search, we don’t want to send too many calls to server
suggestive text, user types something and we suggest the text like google search
scrolling, user scrolls too much, the scroll event should not fire too much
We can create debouncing decorator and enable debouncing to any function:
function debounce(f, timespan) { let timeoutId; return function (...args) { if (timeoutId) { // Not the first time firing clearTimeout(timeoutId); } timeoutId = setTimeout(() => { f.apply(this, args); }, timespan); };}let f = debounce(console.log, 1000);f("a");setTimeout(() => f("b"), 200);setTimeout(() => f("c"), 500);setTimeout(() => f("d"), 1700);setTimeout(() => f("e"), 1900);// Should print c// Should print e
Using lodash in React.js
import {useCallback} from 'react';import _debounce from 'lodash/debounce';import axios from 'axios';function Input() { const [value, setValue] = useState(''); const debounceFn = useCallback(_debounce(handleDebounceFn, 1000), []); function handleDebounceFn(inputValue) { axios.post('/endpoint', { value: inputValue, }).then((res) => { console.log(res.data); }); } function handleChange (event) { setValue(event.target.value); debounceFn(event.target.value); }; return <input value={value} onChange={handleChange} />}
Throttling
Enforces a maximum number of times a function can be called over time.
Execute this function at most once every 100 milliseconds.
Good for regular updates that shouldn’t be very often.
In throttling with 1000ms:
The first call will always happen
It will start waiting for 1000ms and ignore all calls in this period
After 1000ms it will execute the last call (apart from first call)
Go to Step 2
Use:
Tracking Mouse movements
Wait until the user stops resizing the window
Throttling Decorator
Throttle vs Debounce
Throttle ⇒ Rate (of executions per unit of time)
Debounce ⇒ Wait (time before execution happens)
Delay Decorator
Decorator to delay the execution of given function by some time
function delay(f, timespan) { return function (...args) { setTimeout(() => { f.apply(this, args); }, timespan); };}let f1000 = delay(console.log, 1000);let f1500 = delay(console.log, 1500);f1000("test"); // shows "test" after 1000msf1500("test"); // shows "test" after 1500ms
Spy Decorator
Create a decorator spy(func) that should return a wrapper that saves all calls to function in its calls property.
function spy(f) { function wrapper(...args) { wrapper.calls.push(args); // return is needed if the method needs to return stuff return f.apply(this, args); } // After calling spy the returned function should immediately have `calls` property wrapper.calls = []; return wrapper;}function work(a, b) { return a + b;}let f = spy(work);console.log(f(1, 2)); // 3console.log(f(4, 5)); // 9for (let args of f.calls) { console.log("call:" + args.join()); // "call:1,2", "call:4,5"}
Caching Decorator
function cachingDecorator(func) { let cache = new Map(); return function (...args) { const key = args.join(); if (cache.has(key)) { console.log("Retrieved from cache"); return cache.get(key); } let result = func.apply(this, args); cache.set(key, result); return result; };}// Flexible function to perform summation of any number of argumentsfunction sum(...args) { return args.reduce((prev, cur) => cur + prev, 0);}let f = cachingDecorator(sum);console.log(f(3, 4)); // 7console.log(f(2, 3, 4, 5)); // 14console.log(f(3, 4, 5)); // 12console.log(f(3, 4));// Retrieved from cache// 7