2

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

RizkiDPrast
  • 1,695
  • 1
  • 14
  • 21
  • 1
    Is that really the function you got? It doesn't work and can't be used to throttle anything. – Bergi Nov 08 '16 at 12:26
  • 2
    "_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_" -> Nope: https://jsfiddle.net/vpsvdts8/ -> [How do JavaScript closures work?](https://stackoverflow.com/questions/111102/how-do-javascript-closures-work?rq=1) – Andreas Nov 08 '16 at 12:35
  • @Kaiido `runOnce` only returns `undefined` – Andreas Nov 08 '16 at 12:36
  • @Andreas, yep completely misread... Indentation... – Kaiido Nov 08 '16 at 12:37
  • how come??... sorry, let me check it again – RizkiDPrast Nov 08 '16 at 12:59
  • ya the real question should be how to make that runOnce become a throttle function still learning Closure's link given by @Andreas – RizkiDPrast Nov 08 '16 at 13:42

2 Answers2

0

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);
RizkiDPrast
  • 1,695
  • 1
  • 14
  • 21
0

How to limit the number of calls in a specific timeframe ( for example calling of XYZ() ):

var throttleCallsObj = new Object({ maxCallsPerFrame: 10, mSecFrame: 2000 });

function isCallBlocked(key)
{
    var nowDateTime = Date.now();

    if (typeof throttleCallsObj[key] === 'undefined')
        throttleCallsObj[key] = new Object;
    else
    {
        if (throttleCallsObj[key].dt > nowDateTime)
            return throttleCallsObj[key].nCalls >= throttleCallsObj.maxCallsPerFrame;
    }

    throttleCallsObj[key].dt = nowDateTime + throttleCallsObj.mSecFrame;
    throttleCallsObj[key].nCalls = 0;
    return false;
}


function countUnblockedCalls(key)
{
    if (typeof throttleCallsObj[key] === 'undefined')
        return;

    throttleCallsObj[key].nCalls += 1;
    return throttleCallsObj[key].nCalls == throttleCallsObj.maxCallsPerFrame;
}

Usage:

function showMessage_A()
{
    if (isCallBlocked("typeA", 5, 200))
        return;

    /* your code ... */
     countUnblockedCalls("typeA", 200);
    XYZ();

}

function showMessage_B()
{
    if (isCallBlocked("typeB"))
        return;

    /* your code ... */
     countUnblockedCalls("typeB");
     XYZ();
}

The countUnblockedCalls is made as a separate function, because it can be skipped if your code does not call XYZ().