首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用闭包限制函数调用

使用闭包限制函数调用
EN

Code Review用户
提问于 2016-04-22 03:57:29
回答 1查看 111关注 0票数 2

问题陈述:

我们的web应用程序中有许多功能被调用得太频繁了。我们希望您创建一个函数,给定一个函数和一个时间间隔,返回一个新函数,我们可以随时调用它,但确保每个间隔调用原始函数的次数不超过一次。示例用法: limitedDoSomething = rateLimit(doSomething,500);现在,对limitedDoSomething的调用只会调用doSomething,但不会超过每500毫秒调用一次。

测试用例:

代码语言:javascript
运行
复制
function logHello(){ // just a sample function
  console.log('Hello!'); 
}

limitedDoSomething = rateLimit(logHello, 500);

limitedDoSomething(); // should log “Hello!”

window.setTimeout(function(){
  limitedDoSomething();  // should not log “Hello!"
}, 400);

window.setTimeout(function(){
  limitedDoSomething();  // should log “Hello!"  
}, 500);

我的解决方案:

代码语言:javascript
运行
复制
function rateLimit(func, limit){
  var lastInvokedTimestamp;

  return function(){
    if(typeof lastInvokedTimestamp === 'undefined' || Date.now() - lastInvokedTimestamp >= limit){
      lastInvokedTimestamp = Date.now();
      console.log('go ahead!');
      return func();
    } else {
      console.log('too early!');
      return;
    }
  };

}

// run test cases
function logHello(){ // just a sample function
  console.log('Hello!'); 
}

limitedDoSomething = rateLimit(logHello, 500);

limitedDoSomething(); // should log “Hello!”

window.setTimeout(function(){
  limitedDoSomething();  // should not log “Hello!"
}, 400);

window.setTimeout(function(){
  limitedDoSomething();  // should log “Hello!"  
}, 500);

等效jsBin

我很想知道是否有办法改进我的解决方案。

EN

回答 1

Code Review用户

回答已采纳

发布于 2016-04-22 07:02:34

这叫做脱去 函数,您做得很好。

以下是我能想到的一些小改进。没什么大不了的:

  1. 初始化lastInvokedTimestamp,这样就不会是undefined了。
  2. 缓存当前时间。
  3. 跟踪下一次呼叫的阈值,这样它就变成了每个间隔加一次,而不是每个入口减一次。
  4. 将参数传递到已取消的函数中。
  5. 简化测试用例的setTimeout
代码语言:javascript
运行
复制
function rateLimit ( func, interval ) {
  var nextInvokeTimestamp = 0;

  return function(){
    var now = Date.now();
    if ( now < nextInvokeTimestamp  ) {
      return console.log('too early!');
    }
    nextInvokeTimestamp = now + interval;
    console.log('go ahead!');
    return func.apply( this, arguments );
  };

}

// run test cases
function logHello( message ){
  console.log( message || 'Hello!' ); 
}
limitedDoSomething = rateLimit( logHello, 500 );
limitedDoSomething( "Welcome!" ); // should log “Welcome!”
setTimeout( limitedDoSomething, 400 );  // should not log “Hello!"
setTimeout( limitedDoSomething, 500 );  // should log “Hello!"

您可能会注意到,David是完全不同的做这事

  • 使用setTimeout将实际调用延迟到稍后的事件循环,而不是当前事件,以使事情稳定下来一些。
  • 由于延迟(可以低到0,即4ms),他可以使用间隔中的最新参数进行调用,例如鼠标的最新移动。更大的间隔可以让您捕捉更多的呼叫,而响应更慢。

这并不是好或坏,只是不同的需要不同的减速带而已。如果您的要求只是“将多个调用简化为一个”,那么您做得很好。

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/126390

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档