Wie kann man Rückrufe in einfachem Englisch erklären? Wie unterscheiden sie sich vom Aufruf einer Funktion aus einer anderen Funktion, die einen Kontext von der aufrufenden Funktion übernimmt? Wie kann ihre Leistungsfähigkeit einem unerfahrenen Programmierer erklärt werden?
Antworten
Zu viele Anzeigen?Es ist immer besser, mit einem Beispiel zu beginnen :).
Nehmen wir an, Sie haben zwei Module A und B.
Sie möchten, dass Modul A benachrichtigt wenn ein Ereignis/eine Bedingung in Modul B eintritt. Modul B hat jedoch keine Ahnung von Ihrem Modul A. Es kennt lediglich eine Adresse zu einer bestimmten Funktion (von Modul A) über einen Funktionszeiger, der ihm von Modul A zur Verfügung gestellt wird.
Alles, was B nun zu tun hat, ist ein "Rückruf" in Modul A, wenn ein bestimmtes Ereignis/eine bestimmte Bedingung eintritt, indem es den Funktionszeiger verwendet. A kann die weitere Verarbeitung innerhalb der Callback-Funktion vornehmen.
*) Ein klarer Vorteil ist, dass Sie alles über Modul A von Modul B abstrahieren. Modul B muss sich nicht darum kümmern, wer/was Modul A ist.
Johny, der Programmierer, braucht einen Hefter, also geht er in die Abteilung für Bürobedarf und fragt nach einem. Nachdem er das Anforderungsformular ausgefüllt hat, kann er entweder dastehen und darauf warten, dass der Angestellte sich im Lager nach dem Hefter umsieht (wie ein blockierender Funktionsaufruf), oder er kann in der Zwischenzeit etwas anderes tun.
Da dies in der Regel einige Zeit in Anspruch nimmt, fügt Johny dem Anforderungsformular eine Notiz bei, in der er darum bittet, ihn anzurufen, wenn der Hefter abholbereit ist, damit er in der Zwischenzeit etwas anderes tun kann, z. B. ein Nickerchen auf seinem Schreibtisch.
Stellen Sie sich vor, Sie brauchen eine Funktion, die 10 zum Quadrat zurückgibt, also schreiben Sie eine Funktion:
function tenSquared() {return 10*10;}
Später brauchst du 9 zum Quadrat, also schreibst du eine andere Funktion:
function nineSquared() {return 9*9;}
Schließlich werden Sie alle diese Funktionen durch eine generische Funktion ersetzen:
function square(x) {return x*x;}
Die gleiche Überlegung gilt für Rückrufe. Sie haben eine Funktion, die etwas tut und nach Abschluss doA aufruft:
function computeA(){
...
doA(result);
}
Wenn Sie später genau dieselbe Funktion doB aufrufen wollen, können Sie die gesamte Funktion duplizieren:
function computeB(){
...
doB(result);
}
Oder Sie könnten eine Callback-Funktion als Variable übergeben und müssten die Funktion nur einmal ausführen:
function compute(callback){
...
callback(result);
}
Dann müssen Sie nur noch compute(doA) und compute(doB) aufrufen.
Abgesehen von der Vereinfachung des Codes kann asynchroner Code Ihnen mitteilen, dass er abgeschlossen ist, indem er bei Abschluss eine beliebige Funktion aufruft, ähnlich wie wenn Sie jemanden am Telefon anrufen und eine Rückrufnummer hinterlassen.
Du fühlst dich krank, also gehst du zum Arzt. Er untersucht Sie und stellt fest, dass Sie Medikamente brauchen. Er verschreibt Ihnen einige Medikamente und ruft das Rezept in Ihrer örtlichen Apotheke an. Du gehst nach Hause. Später ruft Ihre Apotheke an, um Ihnen mitzuteilen, dass Ihr Rezept fertig ist. Sie gehen hin und holen es ab.
Es gibt zwei Punkte zu erklären, zum einen, wie ein Callback funktioniert (Übergabe einer Funktion, die ohne Kenntnis ihres Kontexts aufgerufen werden kann), zum anderen, wofür er verwendet wird (asynchrone Verarbeitung von Ereignissen).
Die Analogie des Wartens auf ein Paket, die in anderen Antworten verwendet wurde, ist eine gute Erklärung für beides. In einem Computerprogramm würden Sie dem Computer sagen, dass er ein Paket erwarten soll. Normalerweise würde er nun dasitzen und warten (und nichts anderes tun), bis das Paket eintrifft, möglicherweise auf unbestimmte Zeit, wenn es nie eintrifft. Für Menschen klingt das albern, aber für einen Computer ist das ohne weitere Maßnahmen völlig natürlich.
Jetzt wäre der Rückruf die Klingel an Ihrer Haustür. Sie geben dem Paketdienst eine Möglichkeit, Sie über die Ankunft des Pakets zu benachrichtigen, ohne dass er wissen muss, wo (und ob) Sie sich im Haus befinden oder wie die Klingel funktioniert. (Da Sie eine "Rückruffunktion" zur Verfügung gestellt haben, die jederzeit und kontextunabhängig "aufgerufen" werden kann, brauchen Sie jetzt nicht mehr vor der Haustür zu sitzen und können das Ereignis (die Ankunft des Pakets) abwickeln, wann immer es an der Zeit ist.