2016-12-12 10 views
3

У Дэвида Уолша отличная реализация debounce here.Вызов функций отладки по их аргументам

// Returns a function, that, as long as it continues to be invoked, will not 
// be triggered. The function will be called after it stops being called for 
// N milliseconds. If `immediate` is passed, trigger the function on the 
// leading edge, instead of the trailing. 
function debounce(func, wait, immediate) { 
    var timeout; 
    return function() { 
     var context = this, args = arguments; 
     var later = function() { 
      timeout = null; 
      if (!immediate) func.apply(context, args); 
     }; 
     var callNow = immediate && !timeout; 
     clearTimeout(timeout); 
     timeout = setTimeout(later, wait); 
     if (callNow) func.apply(context, args); 
    }; 
}; 

Я использую его в производстве и отлично работает.

Теперь я столкнулся с более сложным случаем необходимости дебюта.

У меня есть событие, которое вызывает обработчик события с таким параметром: $ (elem) .on ('onSomeEvent', (e) => {обработчик (e.X)});

Я уверен, что это событие часто срабатывает и вызывает обработчик даже 1000 раз в секунду. Мне не нужно отказываться от самого обработчика. Но в моем случае, для каждого e.X, я хочу, чтобы его вызывали только один раз за период, скажем, 250 мс.

Я думал о создании двухмерного массива, который содержит x и последнее время выполнения, но я не хочу объявлять какие-либо глобальные переменные.

Любые идеи?

* EDIT *

После прочтения @ Тим Вермален ответа я реализовал это так, и это сработало:

export function debounceWithId(func, wait, id, immediate?) { 
     var timeouts = {}; 
     return function() { 
      var context = this, args = arguments; 
      var later = function() { 
       timeouts[id] = null; 
       if (!immediate) func.apply(context, args); 
      }; 
      var callNow = immediate && !timeouts[id]; 
      clearTimeout(timeouts[id]); 
      timeouts[id] = setTimeout(later, wait); 
      if (callNow) func.apply(context, args); 
     }; 
    }; 
+0

'var timeout' не является глобальной переменной в исходном коде? – Bergi

+0

Кажется, к сожалению – Dorad

+0

Не прискорбно, но именно то, что вы хотите? – Bergi

ответ

3

То, что я всегда использую следующее:

var debounce = (function() { 
    var timers = {}; 

    return function (callback, delay, id) { 
     delay = delay || 500; 
     id = id || "duplicated event"; 

     if (timers[id]) { 
      clearTimeout(timers[id]); 
     } 

     timers[id] = setTimeout(callback, delay); 
    }; 
})(); // note the call here so the call for `func_to_param` is omitted 

Я не верю, что в вашем решении есть большая разница, за исключением того факта, что я могу добавить уникальный идентификатор в событиях. Если я правильно понимаю, вам придется обернуть это вокруг handler(e.X).

debounce(func_to_param, 250, 'mousewheel'); 
debounce(func_to_param, 250, 'scrolling'); 
+1

Я сейчас пытаюсь и дам вам знать. – Dorad

+1

Работал как шарм. Я публикую свои изменения для других. – Dorad