Uczymy się debounce. Na początku zdefiniuję, co przez to rozumiem, potem przykład plus mały bonus. Do dzieła.
Zdefinujmy debounce:
- Jeżeli użytkownik wpisze w panel wyszukiwania literę 'a’ i się zatrzyma
- funkcja wyszukaj podpowiedzi na literę 'a’ wykona się od razu
- Jeżeli użytkownik wpisze w panel wyszukiwania literę 'a’, zatrzyma się na 5 sekund (albo 5 godzin) i dopisze 'n’ do a:
- funkcja wyszukaj podpowiedzi na literę 'a’ wykona się od razu
- funkcja wyszukaj podpowiedzi do 'an’ wykona się od razu
- Jeżeli użytkownik w przeciągu 5 sekund wpisze w pasek wyszukiwania 'ann’:
- funkcja wyszukaj podpowiedzi na literę 'a’ wykona się od razu
- funkcja wyszukaj podpowiedzi dla 'an’ zakolejkuje się na następne 5 sekund
- funkcja wyszukaj podpowiedzi dla 'ann’ anuluje 'wyszukaj dla an’ i kolejkuje 'wyszukaj ann’ na następne 5 sekund
- Jeżeli użytkownik wpisze w ciągu 5 sekund 'ann’ potem dopisze 'a’ to:
- funkcja wyszukaj podpowiedzi dla 'a’ ruszy natychmiast
- funkcja wyszukaj podpowiedzi dla 'an’ zakolejkuje się
- funkcja wyszukaj podpowiedzi dla 'ann’ anuluje poprzednią i zakolejkuje się
- funkcja wyszukaj podpowiedzi dla 'anna’ ruszy natychmiast
To teraz piszemy funkcję:
function debounceFunc(func, timeout = 3000){
let timer = null;
return (...args) => {
if (timer === null) {
func(...args);
timer = setTimeout(() => {
timer = null
}, timeout);
} else {
clearTimeout(timer);
timer = setTimeout(() => {
timer = null
func(...args);
}, timeout);
}
};
}
function search(term){
console.log("Im searching " + term);
}
const debouncedSearch = debounceFunc(search, 5000);
debouncedSearch("javascript");
Oczywiście te 5 sekund bardzo umowne. Aż takiego opóźnienia nie dajemy.
A teraz przykład jak NIE robić debounce:
function debounce_leading(func, timeout = 300){
let timer;
return (...args) => {
if (!timer) {
func.apply(this, args);
}
clearTimeout(timer);
timer = setTimeout(() => {
timer = undefined;
}, timeout);
};
}
Czy coś jest nie teges z logiką? Nie wiem, bo nie jest to zbyt czytelny kod, ale zakładam, że jeżeli nie działa jak throttle to jest to debounce, zgodnie z dowolną definicją.
To co jest w tym kodzie nie tak?
Mała podpowiedź:
timer = undefined;
Nigdy, przenigdy nie dopisujmy undefined jako wartość zmiennej. Jedyny przykład zmiennej, która ma prawo być undefined:
let x;
console.log(x);
//undefined
Warunki dla if też powinny być bardziej dokładne, proszę spojrzeć na to:
let x = null;
let y;
let z = 0;
if(!x)
console.log("null is not truthy");
if(!y)
console.log("undefined is not truthy");
if(!z)
console.log("0 is not truthy");
To zero jest szczególnie podstępne gdy chcemy sprawdzić, czy jakiś argument liczbowy (może być 0) został przekazany:
let x = null;
let optional1 = x || 1;
console.log(optional1);
//1
let y = 0;
let optional2 = y || 1;
console.log(optional2);
//1
W takich wypadkach lepiej używać bardziej dokładnych operatorów:
let x = null;
let optional1 = x ?? 1;
console.log(optional1);
//1
let y = 0;
let optional2 = y ?? 1;
console.log(optional2);
//0
No ale co ja tam wiem…