Eine Rückruffunktion ist einfach eine Funktion, die Sie an eine andere Funktion übergeben, damit diese Funktion sie zu einem späteren Zeitpunkt aufrufen kann. Dies tritt häufig bei asynchronen APIs auf . Der API-Aufruf wird sofort zurückgegeben, da er asynchron ist. Sie übergeben ihm also eine Funktion, die die API aufrufen kann, wenn die asynchrone Aufgabe ausgeführt wurde.
Das einfachste Beispiel, das ich mir in JavaScript vorstellen kann, ist die setTimeout()
Funktion. Es ist eine globale Funktion, die zwei Argumente akzeptiert. Das erste Argument ist die Rückruffunktion und das zweite Argument ist eine Verzögerung in Millisekunden. Die Funktion wartet die entsprechende Zeit und ruft dann Ihre Rückruffunktion auf.
setTimeout(function () {
console.log("10 seconds later...");
}, 10000);
Möglicherweise haben Sie den obigen Code schon einmal gesehen, aber nicht bemerkt, dass die Funktion, die Sie übergeben haben, als Rückruffunktion bezeichnet wurde. Wir könnten den obigen Code umschreiben, um ihn offensichtlicher zu machen.
var callback = function () {
console.log("10 seconds later...");
};
setTimeout(callback, 10000);
Rückrufe werden überall in Node verwendet, da Node von Grund auf so aufgebaut ist, dass es bei allem, was es tut, asynchron ist. Auch wenn Sie mit dem Dateisystem sprechen. Aus diesem Grund akzeptieren eine Tonne der internen Knoten-APIs Rückruffunktionen als Argumente, anstatt Daten zurückzugeben, die Sie einer Variablen zuweisen können. Stattdessen wird Ihre Rückruffunktion aufgerufen und die gewünschten Daten als Argument übergeben. Sie können beispielsweise die Knotenbibliothek fs
zum Lesen einer Datei verwenden. Das fs
Modul stellt zwei eindeutige API-Funktionen zur Verfügung: readFile
und readFileSync
.
Die readFile
Funktion ist asynchron, während dies readFileSync
offensichtlich nicht der Fall ist. Sie können sehen, dass sie beabsichtigen, die asynchronen Aufrufe zu verwenden, wann immer dies möglich ist, da sie sie aufgerufen haben readFile
und readFileSync
anstelle von readFile
und readFileAsync
. Hier ist ein Beispiel für die Verwendung beider Funktionen.
Synchron:
var data = fs.readFileSync('test.txt');
console.log(data);
Der obige Code blockiert die Thread-Ausführung, bis der gesamte Inhalt von test.txt
in den Speicher eingelesen und in der Variablen gespeichert wurde data
. Im Knoten wird dies normalerweise als schlechte Praxis angesehen. Es gibt jedoch Situationen, in denen es nützlich ist, z. B. wenn Sie ein schnelles kleines Skript schreiben, um etwas Einfaches, aber Mühsames zu tun, und es Ihnen nicht wichtig ist, jede Nanosekunde Zeit zu sparen, die Sie können.
Asynchron (mit Rückruf):
var callback = function (err, data) {
if (err) return console.error(err);
console.log(data);
};
fs.readFile('test.txt', callback);
Zuerst erstellen wir eine Rückruffunktion, die zwei Argumente akzeptiert err
unddata
. Ein Problem bei asynchronen Funktionen besteht darin, dass es schwieriger wird, Fehler abzufangen, sodass viele APIs im Rückrufstil Fehler als erstes Argument an die Rückruffunktion übergeben. Es wird empfohlen, zu überprüfen, ob err
ein Wert vorliegt, bevor Sie etwas anderes tun. Wenn ja, beenden Sie die Ausführung des Rückrufs und protokollieren Sie den Fehler.
Synchrone Aufrufe haben einen Vorteil, wenn Ausnahmen ausgelöst werden, da Sie sie einfach mit einem abfangen können try/catch
Block .
try {
var data = fs.readFileSync('test.txt');
console.log(data);
} catch (err) {
console.error(err);
}
In asynchronen Funktionen funktioniert das nicht so. Der API-Aufruf wird sofort zurückgegeben, sodass mit dem nichts zu fangen ist try/catch
. Richtige asynchrone APIs, die Rückrufe verwenden, erkennen immer ihre eigenen Fehler und übergeben diese Fehler dann an den Rückruf, wo Sie sie nach Belieben behandeln können.
Zusätzlich zu Rückrufen gibt es jedoch einen anderen beliebten API-Stil, der häufig als Versprechen bezeichnet wird. Wenn Sie darüber lesen möchten, können Sie den gesamten Blog-Beitrag lesen, den ich basierend auf dieser Antwort hier geschrieben habe .