在Javascript中缓存debounced函数

时间:2017-07-23 13:19:39

标签: javascript functional-programming lodash memoization debouncing

我正在尝试创建一个函数包装器,可以使用DOM元素作为参数进行调用,并返回一个与该DOM元素相关联的唯一去抖函数,该元素中包含一些逻辑。

我会一步一步地澄清我的思考过程:

这是原始的去抖功能

hideElementWhenIdle = _.debounce(($el) => {
  if($el.is(":hover"))
    hideElementWhenIdle($el);
  else
    $el.removeClass("visible");
}, 5000);

现在,这个函数工作得非常好,直到我意识到我将debounced函数绑定到它调用的第一个元素。所以,如果我想创建:

hideElementWhenIdle( $("selector-1") );
hideElementWhenIdle( $("selector-2") );
他们基本上会互相辩解。我想要的是每个元素的独特功能。

肮脏的解决方案

当然我可以这样做:

hideElementWhenIdle = function($el) {
  let fn = _.debounce(($el) => {
    // ... same as above
  }, 5000);

  return fn;
}

hideSelector1WhenIdle = hideElementWhenIdle( $("selector-1") );
hideSelector2WhenIdle = hideElementWhenIdle( $("selector-2") );

现在我可以调用两个独立的函数。然而,这显然很脏并且不可扩展(但是,公平地说,我只需要两个元素来应用于函数)。

尝试失败

我以为我可以wrapmemoize我的功能来实现我想做的事情,但经过多次尝试后,我无法围绕正在发生的事情(或者它是否均匀)正确的解决方案)。这是我最近的尝试:

var hideElementWhenIdle = _.wrap(
  _.memoize( 
    function($el) {
      var fn = _.debounce(() => {
        // ... same as above
      }
    ),
  function(func, $el) {
    return func($el);
  }
);

我猜我的问题是_.debounce总是返回相同的值,所以无论$el如何,我总是缓存相同的值。

1 个答案:

答案 0 :(得分:1)

您的解决方案是我认为的方式。或者你需要自己的debouncer:

function debounce(func,time){
   var debouncing=new Map();
   return function(el){
        if(!debouncing.get(el)){
            debouncing.set(el,setTimeout(_=>debouncing.set(el,null),time));
            return func(el);
        }
    };
}

用例:

var func=debounce(function(el){
   $el=$(el);
   if($el.is(":hover"))
      hideElementWhenIdle($el);
   else
     $el.removeClass("visible");
 }, 5000);

func("#sth");
func("#sth");//debounced
func("#sthelse");//not debounced

注意:这不适用于传递jquery对象,因为它们是唯一的。 DOM节点可以工作。

http://jsbin.com/bujocoravu/1/edit?js