throttle.js•2.4 kB
function sleep (ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
/**
* Throttle is a first wrapper function that sets state variables for throttled requests.
* **/
function Throttle () {
// Setting State
let startedAt = null;
let timesCalled = 0;
let inThrottle = false;
/**
* Second wrapper function sets the parameters for throttling (interval and limit number of requests by interval)
* @param {function} fn function that will be used.
* @param {object} opts parameters interval and limit.
* @return decorator function for @param {function} fn
*/
return function settingOptions (fn, opts) {
const ms = opts.interval;
const number = opts.limit;
/**
* Decorator for parent settingOption @function.
* Function is basically if else statement, that checks if the function could be executed right now or need to wait until the end of a delay.
* For the condition, it uses interval and limit options and compares them to the state variables.
* @return result of the executed function from parent settingOption @function
*/
return async function returnedFunction (...args) {
// Set Date Variable if it's Empty
if (!startedAt) startedAt = Date.now();
if (timesCalled < number && Date.now() - startedAt < ms) {
// Execute Parent Function
timesCalled++;
const result = await fn(...args);
return result;
} else {
if (!inThrottle) {
inThrottle = true;
await sleep(ms);
// Reset Conditions After Delay
timesCalled = 0;
startedAt = Date.now();
// Return Called Function
const result = await returnedFunction(...args);
inThrottle = false;
return result;
} else {
// Wait Until Delay Ends
const checkingPromise = new Promise(resolve => {
const interval = setInterval(async () => {
if (!inThrottle) {
clearInterval(interval);
const result = await returnedFunction(...args);
// Resolve Executed Function
return resolve(result);
}
}, 1);
});
const result = await checkingPromise;
return result;
}
}
};
};
}
const throttledRequest = Throttle();
module.exports = throttledRequest;