RizkiDPrast RizkiDPrast - 29 days ago 7
Javascript Question

Understanding throttle in javascript the correct way

hi I'm trying to understand Throttling in javascript.
I have this code



function runOnce(fn, ms) {
if(typeOf(fn) !== "function")
return;
ms = ms || 5000;
var active;
return (function() {
if(active) {
console.log('no hurry please');
} else {
active = setTimeout(fn, ms);
}
})();
};





I want to test using two different functions callback

function x() {
console.log('timeout from x');
}
function y() {
console.log('timeout from y');
}


Now here are my questions:
Calling
runOnce(x);runOnce(x);runOnce(x);
multiple times, the throttle function seems ok (only invoke function x one time)


  1. but why the
    "console.log('no hurry please');" never get invoked?



when i call
runOnce(x);runOnce(x);runOnce(y);runOnce(y);
the function x and function y only be called 1 time, that is good.


  1. but why if i call
    runOnce(x);runOnce(y);runOnce(x);runOnce(y);
    , both function x and function y are called 2 times?



thanks

Answer

the problem is in my runOnce code. it is solved if i move var active outside of function (thanks to @Andreas for the link). and repair the function a bit. The following full code work:

var active, fnArray = [];

function runOnce(fn, ms) {
  if (typeof(fn) !== "function")
    return;
  ms = ms || 5000;
  return (function() {
    if (active && fnArray.indexOf(fn.name) >= 0) {
      console.log('no hurry please');
    } else {
      fnArray.push(fn.name);
      active = setTimeout(function() {
        fnArray = fnArray.filter(function(elm) {
          elm !== fn.name
        });
        fn();
      }, ms);
    }
  })();
};

function x() {
  document.body.innerHTML += 'timeout from x </br>';
}

function y() {
  document.body.innerHTML += 'timeout from y </br>';
}
runOnce(x);
runOnce(x);
runOnce(x);
runOnce(y);
runOnce(x);
runOnce(y);