6

Wie senken Sie die Häufigkeit von Javascript Ereignisabfragen? Die Ereignisse, um die ich mich Sorgen mache, sind onResize und onScroll. Diese Ereignisse können Dutzende Male pro Sekunde ausgelöst werden, wenn jemand die Größe seines Browsers ändert oder nach unten scrollt. Ich möchte, dass diese Ereignisse nur alle 500 ms auftreten. Ich muss also nicht stundenlang meine Event-Handler optimieren und sicherstellen, dass sie keinen Speicher verlieren.Senken Sie die Häufigkeit der Javascript-Ereignisabfrage

Antwort

9
var resizeTimeout; 

window.onresize = function() { 
    if (resizeTimeout) { 
     clearTimeout(resizeTimeout); 
    } 
    resizeTimeout = setTimeout(function() { 
     // Do it! 
    }, 500); 

}); 

Dies löst die setTimeout() Funktion ~ 500 ms, nachdem die Person Ändern der Größe beendet hat.

Die onscroll Version ist sehr ähnlich :)

+3

dieser wird nicht alle 500 ms ausgelöst, er löst nur 500 ms nach dem Stoppen/Pausieren der Größenänderung aus – Andrey

+0

+1 schlage mich dazu. Denken Sie daran, einen Check für 'resizeTimeout' einzuplanen, da dieser beim ersten Mal" undefiniert "ist. – casablanca

+0

@Andrey: Guter Punkt - ich habe das übersehen. – casablanca

5

Sie können nicht wirklich steuern, wie häufig das Ereignis ausgelöst wird, können Sie so etwas wie erinnere mich an die Zeit des ersten Ereignisses Brennen tun, dann auf jeden daraus folgenden, die Sie prüfen, ob es mehr als 500 ms von der ersten - wenn ja, fahren Sie mit dem Event-Handler fort, sonst beenden Sie einfach den Event-Hanlder

+0

+1 für diese Antwort dann, das ist wahrscheinlich, was das OP will. Sie benötigen jedoch zusätzliche Logik, um das letzte Größenänderungsereignis zu verarbeiten. – casablanca

+1

Ich denke, die Timer-Lösung wird sich um das letzte Größenänderungs-Ereignis kümmern, also wäre die wirkliche Lösung eine Kombination der beiden – Andrey

1

Am Anfang Ihres Handlers, überprüfen Sie, ob 500ms seit dem letzten übergeben wurden, und nur zurückgeben, wenn nicht.

1

Sie können nicht verhindern, dass diese Ereignisse ausgelöst werden. Sie tun es immer. Was Sie tun möchten, hören Sie sofort auf, zuzuhören, und behandeln Sie dann das Ereignis, um Wiederholungen zu vermeiden. Dann wird der gesamte Handler nach setTimeout erneut eingerichtet. Es findet keine Rekursion mehr statt, es sei denn, jemand ändert die Größe des Fensters. Ich benutze hier 5000ms, da es einfacher ist, in der Konsole zu arbeiten. Sie sollten nicht mehr als einen Spam in der FF-Konsole alle 5 Sekunden sehen, auch wenn Sie die Größe eines Spas ändern.

(function staggerListen(){ 
    window.onresize = function(){ 
    window.onresize = false; 
    console.log('spam'); 
    setTimeout(staggerListen,5000); 
    }; 
})() 

die Logik zu entscheiden, ob alles, was die Handler Feuer jedes Mal zu tun, sind nach wie vor einen Handler und eine if-Anweisung + Lookup technisch Brennen. Das kann schwer werden.

+0

Wow. Ich bin mir nicht sicher, was der Overhead für das dynamische Hinzufügen/Entfernen des Listener-Callbacks ist, aber +1, um irgendwie trickreich zu sein. :) – Phrogz

0

Kontrolle der Unterstrich debounce Funktion

Erstellt und gibt eine neue entprellten Version des übergebenen Funktion, die seine Hinrichtung aufzuschieben, bis nach Millisekunden seit dem letzten Mal vergangen warten haben sie aufgerufen wurde. Nützlich für das Implementieren von Verhalten, das nur passieren sollte, nachdem die Eingabe nicht mehr ankommt. Beispiel: Rendern einer Vorschau eines Markdown-Kommentars, Neuberechnen eines Layouts, nachdem die Größenänderung des Fensters gestoppt wurde, und so weiter.

Beispiel:

window.onscroll = _.debounce(
    function() { 
     // do something 
    }, 500, false 
); 
0

habe ich es machen wie auf der akzeptierte Antwort, aber das Problem ist, löst es erst nach dem Timeout angegeben. Ich wollte eine Lösung, die die Größenänderung sofort übernimmt. Hier ist, was ich getan habe.

var _resize_is_busy = false; 
var _resize_scheduled = false; 
var _resize_precision = 100; 

// This register for window resize events. No need to change anything. 
$(window).resize(function() { 

    if (!_resize_is_busy) { 

     // call the scheduler who will do the work and set a timer to 
     // check of other resizes occured within a certain period of time 

     _resize_scheduler(); 
    } 
    else { 

     // the resizer is busy, i.e. a resize have been handled a little 
     // time ago and then the scheduler is waiting some time before 
     // handling any other resize. This flag tells the scheduler that 
     // a resize event have been receive while he was sleeping. 

     _resize_scheduled = true; 
    } 
}); 

// This is the scheduler. No need to change anything. 
var _resize_scheduler = function() { 

    _resize_is_busy = true; 
    _resize_scheduled = false; 

    setTimeout(function() { 

     _resize_is_busy = false; 

     if (_resize_scheduled) 
      _handle_resize(); 

    }, _resize_precision); 

    _handle_resize(); 
} 

var _handle_resize = function() { 

    console.log('DOING ACTUAL RESIZE'); 

    // do the work here 
    //... 
} 

Ich hoffe, dass dies helfen wird.

Verwandte Themen