【问题标题】:Understanding throttle in javascript the correct way正确理解javascript中的节流阀
【发布时间】:2017-03-22 01:50:30
【问题描述】:

您好,我正在尝试了解 javascript 中的节流。 我有这个代码

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);      
            }
          })();      
};

我想使用两个不同的回调函数进行测试

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

现在这是我的问题: 多次调用runOnce(x);runOnce(x);runOnce(x);,油门函数似乎没问题(只调用function x一次)

  1. 但是为什么 "console.log('no rush please');" 永远不会被调用?

当我调用runOnce(x);runOnce(x);runOnce(y);runOnce(y); 时,函数 x 和 函数 y 只被调用 1 次,这很好。

  1. 但是为什么如果我调用runOnce(x);runOnce(y);runOnce(x);runOnce(y);,function x 和 function y 都会被调用 2 次?

谢谢

【问题讨论】:

  • 这真的是你得到的功能吗?它不起作用,也不能用来限制任何东西。
  • "当我调用 runOnce(x);runOnce(x);runOnce(y);runOnce(y); 函数 x 和函数 y 只被调用 1 次,很好" -> 不:jsfiddle.net/vpsvdts8 -> How do JavaScript closures work?
  • @Kaiido runOnce 只返回undefined
  • @Andreas,是的,完全误读了...缩进...
  • 怎么会??...对不起,让我再检查一遍

标签: javascript closures throttling


【解决方案1】:

问题出在我的 runOnce 代码中。 如果我将 var active 移到函数之外,它就会解决(感谢@Andreas 提供的链接)。并稍微修复一下功能。以下完整代码工作:

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);

【讨论】:

    【解决方案2】:

    如何限制特定时间范围内的调用次数(例如调用 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;
    }
    

    用法:

    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();
    }
    

    countUnblockedCalls 是一个单独的函数,因为如果您的代码不调用 XYZ(),则可以跳过它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-02
      • 2021-12-10
      • 2020-01-22
      • 2012-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多