Performance im Browser mit Timeouts verbessern

Performance im Browser mit Timeouts verbessern

Eine Homepage, oder eine Webanwendung, kann interaktiv sein. Je nach Maus- oder Scrollbewegung kann etwas passieren. Am Beispiel eines Event-Listeners möchte ich mal kurz demonstrieren, wie insbesondere bei komplexeren Seiten die Performance verbessert werden kann.

Hat die aktuelle Seite ein oder mehrere Event-Listener für das Scroll-Event registriert, wird mit jeder Maus oder Wischbewegung das Event ausgelöst. Mal angenommen, das Event führt eine Funktion aus. Beim Scrollen wird die Funktion somit immer wieder ausgeführt, bis ich als Benutzer fertig bin. Währenddessen kann mithilfe eines Timeouts die Anzahl der Funktionsaufrufe gedeckelt werden.

Ohne Timeout wird die Funktion auf dem Scrollweg von 100 Pixeln je nach Browser auch 100 Mal aufgerufen. Wenn ich nun ein Timeout einbaue, dass den Funktionsaufruf auf 3x pro Sekunde beschränkt, wird diese ggf. nur noch 3 oder 4x aufgerufen. Dadurch wird der Browser entlastet, und insbesondere auf mobilen Geräten: Energie gespart.

const debounce = (callback, wait) => {
    let reference = null;
    return (...args) => {
        window.clearTimeout(reference);
        reference = window.setTimeout(() => {
            callback.apply(null, args);
        }, wait);
    };
};

Diese Timeout-Funktion wird auch debounce genannt. Eine Beispiel-Implementierung ist oben zu sehen. Diese funktioniert in allen aktuellen Browsers (Chrome, Safari, Edge, Firefox). Werden bereits Frameworks genutzt, kann auch eine debounce-Funktion vorhanden sein. 

Ein Event kann mithilfe von debounce nun wie folgt definiert werden:

const title = document.querySelector('.my-position');

function myCustomEvent() {
    if (!title) {
        return;
    }
    title.innerText = window.scrollY;
}
// Erstaufruf der Funktion
myCustomEvent();

// Aufruf durch Scrollen im 300 Millisekunden Interval
window.addEventListener('scroll', debounce(myCustomEvent, 300));

Das Interval kann beliebig gewählt werden. Je kleiner, desto häufiger erfolgt der Aufruf – und umso flüssiger fühlt sich die Änderung für den Nutzer an. Insbesondere bei Seiten, die besonders viele Event-Listener registriert haben, werden die Vorteile sichtbar. Hier können wichtigere Events häufiger, und sekundäre Events später ausgeführt werden.

Alle vor dem Event bereits existierenden Elemente, sollten außerhalb des Events referenziert werden. Wie im Beispiel oben. Dadurch wird verhindert, dass während des Events das Element nicht im DOM gesucht werden muss.