2016-12-12 3 views
3

David Walsh hat eine große Entprellen-Implementierung here.Entprellen Funktionsaufrufe durch ihre Argumente

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

Ich benutze es in der Produktion und es funktioniert gut.

Jetzt habe ich einen etwas komplexeren Fall von Entprellen benötigt.

Ich habe ein Ereignis, das einen Event-Handler mit einem Parameter wie folgt aufruft: $ (elem) .on ('onSomeEvent', (e) => {handler (e.X)});

Ich bin in Ordnung mit diesem Ereignis ausgelöst wird häufig und Aufruf der Handler sogar 1000 Mal pro Sekunde. Ich muss den Handler selbst nicht entprellen. Aber in meinem Fall, für jeden e.X, möchte ich, dass es nur einmal in einem Zeitraum aufgerufen wird, sagen wir 250ms.

Ich dachte über die Erstellung eines zweidimensionalen Arrays, das die x und die letzte Laufzeit enthält, aber ich möchte keine globalen Variablen deklarieren.

Irgendwelche Ideen?

* EDIT *

Nach Antwort @ Tim Vermaelen Lesen ich habe es so umgesetzt, und es funktionierte:

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' ist auch keine globale Variable im ursprünglichen Code? – Bergi

+0

Scheint leider zu sein – Dorad

+0

Nicht unglücklich, aber genau was willst du? – Bergi

Antwort

3

Was ich immer verwenden ist folgende:

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 

Ich glaube nicht, dass es einen großen Unterschied zu Ihrer Lösung gibt, abgesehen von der Tatsache, dass ich in den Ereignissen eindeutige IDs hinzufügen kann. Sie müssen dies um handler(e.X) wickeln, wenn ich richtig verstehe.

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

Ich versuche jetzt und werde Sie wissen lassen. – Dorad

+1

Arbeitete wie ein Charme. Ich poste meine Modifikation für andere. – Dorad