W3docs

JavaScript Callbacks

In JavaScript sind Callbacks ein grundlegendes Konzept für asynchrone Operationen. Sie sind Funktionen, die einer anderen Funktion übergeben werden.

Ein Callback ist schlicht eine Funktion, die einer anderen Funktion als Argument übergeben wird, damit die empfangende Funktion sie zu einem späteren Zeitpunkt aufrufen kann. Da Funktionen in JavaScript First-Class-Werte sind — sie können in Variablen gespeichert, weitergereicht und zurückgegeben werden — kann jede Funktion eine andere Funktion als Parameter entgegennehmen. Dieses eine Konzept treibt alles an, von array-Methoden wie map bis hin zu Timern und Netzwerkanfragen.

Dieses Kapitel behandelt, was Callbacks sind, den Unterschied zwischen synchronen und asynchronen Callbacks, die Error-First-Konvention, das Problem des Callback Hells und wie Promises und async/await dieses lösen.

Ein erster Callback

Die übergebene Funktion ist der Callback; die Funktion, die ihn empfängt und aufruft, ist die Höherordnungsfunktion. Hier läuft ein Callback, nachdem eine Aufgabe abgeschlossen ist:

javascript— editable

finishTask wird an completeTask übergeben und darin aufgerufen. Beachte, dass du den Funktionsnamen (finishTask) ohne Klammern übergibst — das Hinzufügen von () würde sie sofort aufrufen und stattdessen ihren Rückgabewert übergeben.

Synchrone vs. asynchrone Callbacks

Nicht jeder Callback hat mit Warten zu tun. Es gibt zwei verschiedene Arten, und sie zu verwechseln ist eine häufige Fehlerquelle.

Synchrone Callbacks

Ein synchroner Callback wird sofort und in Reihenfolge ausgeführt, bevor die äußere Funktion zurückkehrt. Array-Methoden sind das klassische Beispiel:

javascript— editable

Hier wird transform für jedes Element aufgerufen und abgeschlossen, bevor map zurückkehrt. Eingebaute Methoden wie Array.prototype.map, filter, forEach und sort nehmen alle synchrone Callbacks entgegen.

Asynchrone Callbacks

Ein asynchroner Callback wird an eine Operation übergeben, die später abgeschlossen wird — ein Timer, ein Datei-Lesevorgang oder eine Netzwerkanfrage. Die äußere Funktion kehrt sofort zurück, und der Callback wird ausgelöst, sobald das Ergebnis bereit ist. JavaScript plant diese Ausführungen über den Event Loop, der Callbacks in eine Warteschlange einreiht und sie ausführt, wenn der Call Stack leer ist.

javascript— editable

Selbst bei einer Verzögerung von 0 ms läuft der Callback nach dem umgebenden synchronen Code. Das ist das definierende Merkmal eines asynchronen Callbacks: Er kann auf normalem Weg keinen Wert zurückgeben, sodass die einzige Möglichkeit, das Ergebnis zu verwenden, darin besteht, den Fortsetzungscode innerhalb des Callbacks zu platzieren. Um genau zu verstehen, wann diese ausgeführt werden, siehe JavaScript: Event Loop.

Die Error-First-Konvention

Asynchrone Callbacks können kein throw an den Code senden, der die Operation gestartet hat — wenn sie ausgeführt werden, ist dieser Code längst zurückgekehrt. Die Community hat sich auf eine Konvention geeinigt: den Fehler als erstes Argument und das Ergebnis als zweites übergeben. Der Callback prüft zuerst immer den Fehler.

javascript— editable

Wenn alles erfolgreich ist, ist der Fehler-Slot null. Diese (err, result)-Signatur ist der Standard in den Node.js-APIs (fs.readFile, dns.lookup und vielen mehr).

Callback Hell: Die Pyramide des Untergangs

Callbacks funktionieren gut für eine einzelne Operation. Das Problem beginnt, wenn ein asynchroner Schritt vom Ergebnis des vorherigen abhängt. Jeder Schritt wird innerhalb des letzten verschachtelt, und die Einrückung wandert nach rechts — die sogenannte Pyramide des Untergangs:

javascript— editable

Mit zwei Schritten ist es noch lesbar. Füge einen dritten und vierten hinzu — und wiederhole die if (err)-Prüfung auf jeder Ebene — und der Code wird schwer nachzuvollziehen, schwer zu handhaben und schwer zu ändern. Das ist Callback Hell, und es ist der Hauptgrund, warum Promises eingeführt wurden.

Best Practices für die Verwendung von Callbacks

Obwohl Callbacks mächtig sind, kann ihre übermäßige oder unsachgemäße Verwendung zu „Callback Hell" führen, bei der der Code zu tief verschachtelt und schwer lesbar und wartbar wird. Hier sind einige Best Practices, um deinen Code sauber zu halten:

  1. Modularisiere deinen Code: Teile deine Callback-Funktionen in kleinere, wiederverwendbare Funktionen auf. Dieser Ansatz verbessert nicht nur die Lesbarkeit, sondern auch die Code-Wartung.
  2. Behandle Fehler sorgfältig: Behandle in deinen Callbacks immer Fehler. Diese Praxis verhindert Abstürze und unerwünschtes Verhalten in Produktionsumgebungen.
  3. Vermeide tiefe Verschachtelung: Versuche, deine Callback-Strukturen so flach wie möglich zu halten. Werkzeuge wie async/await oder Promises können helfen, asynchrone Operationen sauberer zu verwalten.
  4. Achte auf Closures in Schleifen: Wenn du Callbacks innerhalb von Schleifen definierst, verwende let oder const für Schleifenvariablen, um Closure-bedingte Fehler zu vermeiden, bei denen alle Callbacks den letzten Schleifenwert erfassen.

Über Callbacks hinausgehen: Promises und Async/Await

Während Callbacks ein grundlegender Bestandteil von JavaScript sind, bietet modernes JavaScript abstrahiertere Möglichkeiten zur Handhabung asynchronen Codes, wie Promises und async/await.

Promises verwenden

Ein Promise stellt einen Wert dar, der jetzt, in der Zukunft oder niemals verfügbar sein kann. Anstatt zu verschachteln, werden abhängige Schritte nacheinander verkettet, was die Pyramide abflacht und die Fehlerbehandlung in einem einzigen .catch zentralisiert. Beginne mit JavaScript: Promises und sieh dann, wie Schritte in JavaScript: Promises Chaining verbunden werden.

Wenn du eine alte callback-basierte Funktion hast (wie die obigen Beispiele divide oder getUser), kannst du sie so einwickeln, dass sie ein Promise zurückgibt — eine Technik namens Promisifizierung. Siehe JavaScript: Promisification.

Async/Await: Ein saubererer Ansatz

Die async/await-Syntax ermöglicht es dir, asynchronen Code zu schreiben, der wie synchroner Code aussieht. Sie basiert auf Promises und ist intuitiver als traditionelle Callback-Muster. Lies JavaScript: Async/Await, um zu sehen, wie du async/await statt Callbacks verwenden kannst.

Fazit

Das Verstehen und effektive Nutzen von Callbacks ist für JavaScript-Entwickler entscheidend. Indem du Best Practices befolgst und moderne Features wie Promises und async/await nutzt, kannst du saubereren, besser wartbaren Code schreiben. Meistere diese Konzepte, um deine JavaScript-Programmierkenntnisse zu verbessern und effizientere Anwendungen zu erstellen.

Übungen

Übung
Was ist eine Callback-Funktion in JavaScript und wann wird sie ausgeführt?
Was ist eine Callback-Funktion in JavaScript und wann wird sie ausgeführt?
Was this page helpful?