Jeden z ważniejszych konceptów we frontendowym programowaniu w JavaScript, czyli throttle. Poznajemy czym jest i jak go używać.
Cóż, zasada jest prosta:
- Funkcja throttle przyjmuje funkcję i opóźnienie
- Gdy funkcja jest throttled sprawdzane jest, czy przez ostatnie n-sekund nie była wywoływana
- Jeżeli przez ostatnie n-sekund funkcja nie była wywoływana, to się wywoła
Napiszmy sobie throttle:
function throttle(mainFunction, delay) {
let timerFlag = null;
return (...args) => {
if (timerFlag === null) {
mainFunction(...args);
//obsługa timerFlag
}
};
}
Cóż, widzimy funkcję wyższego rzędu przyjmującą func i delay, domknięcie na zmienną timerFlag, zwrócenie funkcji, której dajemy argumenty i jeżeli timerFlag jest nullem to ją wywołujemy z argumentami.
Dla uproszczenia napiszmy sobie jeszcze funkcję once:
function oncify(mainFunction) {
let executedFlag = false;
return (...args) => {
if (executedFlag === false) {
mainFunction(...args);
executedFlag = true;
}
};
}
function sayHello(name) {
console.log("Hello " + name);
}
const helloOnce = oncify(sayHello);
helloOnce("John");
//Hello John
helloOnce("John");
//nic...
Tu zasada jest prosta – jeżeli kiedykolwiek wcześniej tę funkcję wywołano to nie wolno jej wywołać ponownie.
W throttle ma to wyglądać inaczej – jeżeli nie wywołano jej przez n-sekund to można ją wywołać:
function throttle(mainFunction, delay) {
let timerFlag = null;
return (...args) => {
if (timerFlag === null) {
mainFunction(...args);
timerFlag = setTimeout(() => {
timerFlag = null;
}, delay);
}
};
}
Czyli tak:
- Bierz func i delay
- Przez closure ustaw flag na null
- Zwracaj funkcję, która przyjmuje dowolne argumenty
- Jeżeli flaga jest nullem, wywołaj func z argumentami
- Ustaw timeout na ponowne zanullowanie flagi
- Do czasu zapełnienia nullem timerFlag będzie mieć zwracany przez setTimeout timerID…
Tyle tytułem throttle, ale jeszcze proponuję powrót do oncify i danie możliwości zwracania wartości (przy jednorazowym wywołaniu):
function oncify(mainFunction) {
let executedFlag = false;
let res = null
return (...args) => {
if (executedFlag === false) {
res = mainFunction(...args);
executedFlag = true;
}
return res;
};
}
function sayHello(name) {
console.log("Hello " + name);
return 42;
}
const helloOnce = oncify(sayHello);
helloOnce("John");
//Hello John
helloOnce("John");
//nic...
console.log(helloOnce("John"))
//42