The throttle part
An easy way to throttle function calls is to use a flag (boolean variable). It works like this:
- Set the flag to
false
- In your throttled function, don't do anything if the flag is set to
true
- Otherwise, set it to
true
and execute your function
- When it's done, reset the flag to
false
, to allow later calls
The interval part
If you want to execute a function every X
seconds, your best choice is to use setTimeout
or setInterval
. However, there are multiple ways to do it, and depending on your usage, you might prefer using one or the other. For example, with this code:
setInterval(myFunc, 5000);
Your function will wait 5 seconds before being executed.
If you want the first execution to happen immediatly, you can do this (using an IIFE here):
(function myInterval(){
myFunc();
setTimeout(myInterval, 5000);
})();
The result, with your code
I adapted your code below to incorporate these changes:
class Test {
rangeListener(range, options) {
/*
* This flag will be set to true when we are waiting
* for the next AnimationFrame, and back to false
*/
let throttling = false;
let timer;
/*
* Functions
*/
const changeListener = () => {
if (!options.onChange) return;
options.onChange(range.value);
};
const stepListener = () => {
if (!options.onStep || throttling) return;
throttling = true;
window.requestAnimationFrame(() => {
options.onStep(range.value);
throttling = false;
});
};
const intervalFunc = (isInitialization = false) => {
if (!options.onInterval) return;
options.onInterval(range.value);
if (!isInitialization) {
timer = setTimeout(intervalFunc, options.delay || 500);
}
};
/*
* Event listeners
*/
range.addEventListener("change", changeListener);
range.addEventListener("mousedown", () => {
clearTimeout(timer);
intervalFunc();
stepListener();
range.addEventListener("mousemove", stepListener);
});
range.addEventListener("mouseup", () => {
// Execute it once more to get the last value
intervalFunc();
clearTimeout(timer);
range.removeEventListener("mousemove", stepListener);
});
range.addEventListener("keydown", stepListener);
/*
* Values initialization
*/
changeListener();
stepListener();
intervalFunc(true);
}
}
let test = new Test();
const setHTML = (selector, value) => {
document.querySelector(selector).innerHTML = value;
};
test.rangeListener(document.querySelector(".range"), {
onChange: (value) => setHTML(".value", value),
onStep: (value) => setHTML(".step", value),
onInterval: (value) => setHTML(".delayed", value),
delay: 300
});
<input type="range" class="range" min="1" max="100" value="1">
<div>onChange: <span class="value">0</span></div>
<div>onStep: <span class="step">0</span></div>
<div>onInterval: <span class="delayed">0</span></div>