Manche Browser-Events feuern in rasender Geschwindigkeit. Ein einziges Scrollen kann Dutzende, beim Tippen in ein Suchfeld jeder Tastenanschlag ein eigenes Ereignis auslösen. Wenn an jedem dieser Ereignisse aufwendige Arbeit hängt – ein Netzwerk-Aufruf, eine Neuberechnung des Layouts, ein Re-Render – wird die Oberfläche schnell träge. Genau hier setzen zwei Techniken an, die zu den wichtigsten Werkzeugen für flüssiges Frontend gehören: Debounce und Throttle. Beide drosseln die Häufigkeit, mit der eine Funktion tatsächlich läuft, gehen aber unterschiedlich vor. Dieser Ratgeber erklärt den Unterschied praxisnah, zeigt einfache Eigenimplementierungen und hilft bei der Wahl der richtigen Methode.
Das Grundproblem: zu viele Events
Stell dir ein Suchfeld vor, das bei jeder Eingabe eine Anfrage an den Server schickt. Tippt jemand das Wort „Berlin", entstehen sechs Tastenanschläge und damit sechs Anfragen – obwohl nur das letzte Ergebnis interessiert. Ähnlich beim Scrollen: Bindest du dort eine Funktion, die Positionen misst und Elemente einblendet, kann sie hundertfach pro Sekunde laufen. Die Folge sind unnötige Rechenlast, ruckelnde Animationen und im schlimmsten Fall ein blockierter Hauptthread.
Debounce und Throttle lösen das, indem sie zwischen Ereignis und Ausführung eine Steuerung einziehen. Sie unterdrücken überflüssige Aufrufe, ohne dass du die eigentliche Logik anfassen musst.
Was Debounce macht
Debounce verzögert die Ausführung, bis eine bestimmte Zeit lang kein neues Ereignis mehr eingetroffen ist. Solange weiter getippt, gescrollt oder geklickt wird, schiebt sich der Startzeitpunkt immer weiter nach hinten. Erst wenn eine Pause eintritt, läuft die Funktion ein einziges Mal.
Das passt perfekt zum Suchfeld: Erst wenn die Person mit dem Tippen aufhört, lohnt sich die Anfrage. Eine typische Wartezeit liegt im Bereich von etwa 250 bis 500 Millisekunden – kurz genug, dass es sich reaktionsschnell anfühlt, lang genug, um die Flut an Zwischenanfragen abzufangen.
- Verhalten: wartet auf Ruhe, führt dann genau einmal aus.
- Stärke: reduziert auf das eine relevante Endergebnis.
- Risiko: Bei dauerhafter Aktivität läuft die Funktion gar nicht.
Was Throttle macht
Throttle verfolgt einen anderen Ansatz: Es lässt die Funktion höchstens einmal pro festgelegtem Intervall laufen, egal wie viele Ereignisse dazwischen eintreffen. Bei einem Intervall von 200 Millisekunden wird also maximal fünfmal pro Sekunde ausgeführt, selbst wenn der Browser hundert Scroll-Events meldet.
Throttle eignet sich dort, wo regelmäßige Zwischenstände wichtig sind – etwa bei einer Fortschrittsanzeige, die der Scrollposition folgt, oder beim Neuberechnen eines Layouts während des Größenänderns des Fensters. Du willst dort nicht auf eine Pause warten, sondern kontinuierlich, aber kontrolliert reagieren.
- Verhalten: erlaubt eine Ausführung pro Zeitfenster.
- Stärke: garantiert regelmäßige Reaktion auch bei Dauerlast.
- Risiko: Das allerletzte Ereignis kann verloren gehen, wenn man es nicht explizit nachholt.
Debounce vs. Throttle im direkten Vergleich
| Merkmal | Debounce | Throttle |
|---|---|---|
| Auslöselogik | Läuft erst nach einer Eingabepause | Läuft fest getaktet im Intervall |
| Anzahl Ausführungen bei Dauerlast | Erst am Ende, einmalig | Regelmäßig, mehrfach |
| Typische Events | Eingabe, Suchfeld, Auto-Save, Validierung | Scroll, Resize, Mausbewegung, Drag |
| Empfohlene Zeitspanne | ca. 250–500 ms | ca. 100–250 ms |
| Hauptziel | Nur das Endergebnis verarbeiten | Gleichmäßige, gedrosselte Reaktion |
| Gefahr bei Fehlnutzung | Reaktion bleibt ganz aus | Letzter Zustand wird übersprungen |
Einfache Eigenimplementierung mit setTimeout
Beide Techniken lassen sich in wenigen Zeilen selbst schreiben. Der Kern ist immer ein Timer, der gesetzt, verschoben oder geprüft wird.
Eine schlanke Debounce-Variante setzt bei jedem Aufruf den alten Timer zurück und startet ihn neu:
function debounce(fn, wartezeit) {
let timer;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), wartezeit);
};
}
Eine einfache Throttle-Variante merkt sich den Zeitpunkt der letzten Ausführung und lässt erst wieder zu, wenn das Intervall verstrichen ist:
function throttle(fn, intervall) {
let letzterLauf = 0;
return function (...args) {
const jetzt = Date.now();
if (jetzt - letzterLauf >= intervall) {
letzterLauf = jetzt;
fn.apply(this, args);
}
};
}
Wichtig ist, dass beide Hilfsfunktionen das ursprüngliche this und die Argumente korrekt weiterreichen – sonst funktionieren Event-Handler nur eingeschränkt.
Praxisbeispiele aus dem Alltag
- Suchfeld mit Vorschlägen: Debounce auf das Eingabe-Event, damit die Suchanfrage erst nach einer kurzen Tipp-Pause startet.
- Endlos-Scrollen: Throttle auf das Scroll-Event, damit das Nachladen weiterer Inhalte in geregelten Abständen prüft, ob das Seitenende naht.
- Fenstergröße ändern: Throttle auf das Resize-Event, um ein Diagramm oder Layout flüssig, aber nicht bei jedem Pixel neu zu berechnen.
- Auto-Speichern in einem Editor: Debounce, damit erst gespeichert wird, wenn der Nutzer eine Schreibpause macht.
Eigenimplementierung oder Bibliothek?
Für einfache Fälle reichen die obigen Funktionen völlig aus und sparen jede zusätzliche Abhängigkeit. Sobald es um Sonderfälle geht – etwa sofort beim ersten Ereignis auslösen („leading edge"), das letzte Ereignis garantiert nachholen („trailing edge") oder eine maximale Wartezeit erzwingen – greifen viele Teams zu erprobten Hilfsfunktionen aus etablierten Utility-Bibliotheken. Diese decken Randfälle robust ab und sind gut getestet.
Die Faustregel: Wer nur eine Handvoll Handler drosselt, ist mit eigenem Code schneller und schlanker unterwegs. Wer viele unterschiedliche Drosselungen mit Sonderverhalten braucht, profitiert von einer fertigen Lösung. Wenn du verschiedene Ansätze ausprobieren willst, helfen kleine Helfer und Snippet-Werkzeuge wie die kostenlosen Webtools auf kotsch.tech beim schnellen Testen von Logik und Timing.
Häufige Fehler und wie du sie vermeidest
- Funktion bei jedem Render neu erzeugen: Wird der gedrosselte Handler innerhalb einer Render-Funktion neu gebaut, geht der interne Timer-Zustand verloren. Erzeuge ihn nur einmal.
- Falsche Wahl der Technik: Debounce für eine Fortschrittsanzeige fühlt sich „abgehackt" an, Throttle für ein Suchfeld erzeugt unnötige Zwischenanfragen.
- Timer nicht aufräumen: Wird ein Element entfernt, sollte ein laufender Timer per
clearTimeoutbeendet werden, um Speicherlecks und Fehler zu vermeiden. - Zu lange Wartezeiten: Über 600 Millisekunden wirkt die Oberfläche schnell „verzögert" und träge.
Häufige Fragen
Was ist der Hauptunterschied zwischen Debounce und Throttle?
Debounce wartet auf eine Pause und führt dann einmal aus. Throttle erlaubt eine Ausführung pro festem Zeitfenster, auch während dauerhafter Aktivität. Debounce zielt auf das Endergebnis, Throttle auf eine gleichmäßige Taktung.
Welche Wartezeit soll ich wählen?
Für Suchfelder sind etwa 250 bis 500 Millisekunden üblich. Für Scroll- und Resize-Throttling reichen meist 100 bis 250 Millisekunden. Die genauen Werte hängen vom gewünschten Gefühl ab und sollten am echten Gerät getestet werden.
Brauche ich für beides eine externe Bibliothek?
Nein. Beide Techniken lassen sich mit wenigen Zeilen und setTimeout selbst umsetzen. Eine Bibliothek lohnt sich erst, wenn du Sonderfälle wie garantiertes Nachholen des letzten Ereignisses oder eine maximale Wartezeit brauchst.
Kann ich Debounce und Throttle kombinieren?
In der Praxis nutzt man pro Event meist nur eine der beiden Techniken. Manche Bibliotheken bieten aber Optionen, die Eigenschaften beider verbinden, etwa Throttle mit garantierter letzter Ausführung – das deckt viele Mischfälle bereits ab.
Funktionieren diese Techniken auch in React, Vue oder anderen Frameworks?
Ja, das Grundprinzip ist framework-unabhängig. Wichtig ist nur, dass der gedrosselte Handler stabil bleibt und nicht bei jedem Render neu erzeugt wird, sonst geht der interne Timer-Zustand verloren.
Verbessert das wirklich die Performance spürbar?
Gerade bei aufwendigen Handlern an häufig feuernden Events ist der Effekt deutlich. Statt Hunderter Aufrufe pro Sekunde laufen nur wenige, was Hauptthread und Netzwerk entlastet und für flüssigere Bedienung sorgt. Weitere Praxisthemen findest du in den News auf kotsch.tech oder auf der Startseite.