sugar
Version:
A Javascript utility library for working with native objects.
54 lines (50 loc) • 1.63 kB
JavaScript
;
var setDelay = require('./setDelay'),
mathAliases = require('../../common/var/mathAliases');
var max = mathAliases.max,
ceil = mathAliases.ceil,
round = mathAliases.round;
function createLazyFunction(fn, ms, immediate, limit) {
var queue = [], locked = false, execute, rounded, perExecution, result;
ms = ms || 1;
limit = limit || Infinity;
rounded = ceil(ms);
perExecution = round(rounded / ms) || 1;
execute = function() {
var queueLength = queue.length, maxPerRound;
if (queueLength == 0) return;
// Allow fractions of a millisecond by calling
// multiple times per actual timeout execution
maxPerRound = max(queueLength - perExecution, 0);
while(queueLength > maxPerRound) {
// Getting uber-meta here...
result = Function.prototype.apply.apply(fn, queue.shift());
queueLength--;
}
setDelay(lazy, rounded, function() {
locked = false;
execute();
});
};
function lazy() {
// If the execution has locked and it's immediate, then
// allow 1 less in the queue as 1 call has already taken place.
if (queue.length < limit - (locked && immediate ? 1 : 0)) {
// Optimized: no leaking arguments
var args = []; for(var $i = 0, $len = arguments.length; $i < $len; $i++) args.push(arguments[$i]);
queue.push([this, args]);
}
if (!locked) {
locked = true;
if (immediate) {
execute();
} else {
setDelay(lazy, rounded, execute);
}
}
// Return the memoized result
return result;
}
return lazy;
}
module.exports = createLazyFunction;