Wie erklärt man Rückrufe im Klartext? Wie unterscheiden sie sich vom Aufrufen einer Funktion von einer anderen Funktion, wobei ein Kontext von der aufrufenden Funktion übernommen wird? Wie kann ihre Macht einem unerfahrenen Programmierer erklärt werden?
function
callback
language-agnostic
terminology
Yahoo-Me
quelle
quelle
Antworten:
Oft muss eine Anwendung je nach Kontext / Status unterschiedliche Funktionen ausführen. Dazu verwenden wir eine Variable, in der wir die Informationen über die aufzurufende Funktion speichern. Je nach Bedarf setzt die Anwendung diese Variable mit den Informationen über die aufzurufende Funktion und ruft die Funktion mit derselben Variablen auf.
In Javascript ist das Beispiel unten. Hier verwenden wir das Methodenargument als Variable, in der wir Informationen über die Funktion speichern.
quelle
function(arg)
) in derprocessArray(arr,callback)
Funktion tunIch werde versuchen, das absolut einfach zu halten. Ein "Rückruf" ist eine Funktion, die von einer anderen Funktion aufgerufen wird, die die erste Funktion als Parameter verwendet. Ein "Rückruf" ist oft eine Funktion, die aufgerufen wird, wenn etwas passiert. Dass etwas in Programmierersprache als "Ereignis" bezeichnet werden kann.
Stellen Sie sich dieses Szenario vor: Sie erwarten ein Paket in ein paar Tagen. Das Paket ist ein Geschenk für Ihren Nachbarn. Sobald Sie das Paket erhalten haben, möchten Sie es daher zu den Nachbarn bringen. Sie sind nicht in der Stadt und hinterlassen Anweisungen für Ihren Ehepartner.
Sie könnten ihnen sagen, sie sollen das Paket holen und es zu den Nachbarn bringen. Wenn Ihr Ehepartner so dumm wie ein Computer wäre, würden sie an der Tür sitzen und auf das Paket warten, bis es kommt (sonst nichts tun), und wenn es dann kommt, würden sie es zu den Nachbarn bringen. Aber es gibt einen besseren Weg. Sagen Sie Ihrem Ehepartner, dass er das Paket EINMAL über die Nachbarn bringen soll, wenn er es erhält. Dann können sie normal leben, bis sie das Paket erhalten.
In unserem Beispiel ist der Empfang des Pakets das "Ereignis" und das Bringen zu den Nachbarn der "Rückruf". Ihr Ehepartner "führt" Ihre Anweisungen aus, um das Paket erst dann zu bringen, wenn das Paket eintrifft. Viel besser!
Diese Art des Denkens ist im täglichen Leben offensichtlich, aber Computer haben nicht den gleichen gesunden Menschenverstand. Überlegen Sie, wie Programmierer normalerweise in eine Datei schreiben:
Hier warten wir darauf, dass die Datei geöffnet wird, bevor wir darauf schreiben. Dies "blockiert" den Ausführungsfluss und unser Programm kann keine der anderen Dinge tun, die es möglicherweise tun muss! Was wäre, wenn wir dies stattdessen tun könnten:
Es stellt sich heraus, dass wir dies mit einigen Sprachen und Frameworks tun. Es ist ziemlich cool! Schauen Sie sich Node.js an, um sich mit dieser Art des Denkens vertraut zu machen.
quelle
open
funktioniert. Es ist plausibel, dassopen
intern blockiert werden kann, während darauf gewartet wird, dass das Betriebssystem seine schwarze Magie ausführt, auf der der Rückruf ausgeführt wird. In einem solchen Fall gibt es keinen Unterschied im Ergebnis.Im Klartext ist eine Rückruffunktion wie ein Mitarbeiter, der seinen Manager "zurückruft", wenn er eine Aufgabe erledigt hat .
Es ist wahr, dass Sie eine Funktion von einer anderen Funktion aus aufrufen, aber der Schlüssel ist, dass der Rückruf wie ein Objekt behandelt wird, sodass Sie die aufzurufende Funktion basierend auf dem Status des Systems ändern können (wie das Strategieentwurfsmuster).
Die Leistungsfähigkeit von Rückrufen lässt sich leicht auf Websites im AJAX-Stil erkennen, die Daten von einem Server abrufen müssen. Das Herunterladen der neuen Daten kann einige Zeit dauern. Ohne Rückrufe würde Ihre gesamte Benutzeroberfläche beim Herunterladen der neuen Daten "einfrieren", oder Sie müssten die gesamte Seite aktualisieren und nicht nur einen Teil davon. Mit einem Rückruf können Sie ein Bild "Jetzt laden" einfügen und es nach dem Laden durch die neuen Daten ersetzen.
Code ohne Rückruf:
Mit Rückruf:
Hier ist ein Beispiel mit einem Rückruf unter Verwendung von getJSON von jQuery :
Mit Verschluss:
Oft muss der Rückruf über
state
die aufrufende Funktion mit a zugreifenclosure
, ähnlich wie der Mitarbeiter Informationen vom Manager abrufen muss, bevor er seine Aufgabe ausführen kann . Um das zu erstellenclosure
, können Sie die Funktion so einbinden, dass die Daten im aufrufenden Kontext angezeigt werden:Verwendungszweck:
Schließung
Schließlich ist hier eine Definition
closure
von Douglas Crockford :Funktionen können innerhalb anderer Funktionen definiert werden. Die innere Funktion hat Zugriff auf die Variablen und Parameter der äußeren Funktion. Wenn ein Verweis auf eine innere Funktion erhalten bleibt (z. B. als Rückruffunktion), überleben auch die Vars der äußeren Funktion.
Siehe auch:
quelle
Ich bin fassungslos zu sehen, dass so viele intelligente Menschen die Realität nicht betonen, dass das Wort "Rückruf" auf zwei inkonsistente Arten verwendet wird.
In beiden Fällen muss eine Funktion angepasst werden, indem zusätzliche Funktionen (eine anonyme oder benannte Funktionsdefinition) an eine vorhandene Funktion übergeben werden. dh.
Wenn die benutzerdefinierte Funktionalität einfach in den Codeblock eingefügt wird, haben Sie die Funktion wie folgt angepasst.
Obwohl diese Art der injizierten Funktionalität oft als "Rückruf" bezeichnet wird, gibt es nichts Kontingentes daran. Ein sehr offensichtliches Beispiel ist die forEach-Methode, bei der eine benutzerdefinierte Funktion als Argument angegeben wird, das auf jedes Element in einem Array angewendet wird, um das Array zu ändern.
Dies unterscheidet sich jedoch grundlegend von der Verwendung von "Rückruffunktionen" für die asynchrone Programmierung wie in AJAX oder node.js oder einfach durch die Zuweisung von Funktionen zu Benutzerinteraktionsereignissen (wie Mausklicks). In diesem Fall besteht die gesamte Idee darin, auf das Eintreten eines möglichen Ereignisses zu warten, bevor die benutzerdefinierte Funktionalität ausgeführt wird. Dies ist bei Benutzerinteraktionen offensichtlich, aber auch bei E / A-Prozessen (Eingabe / Ausgabe) wichtig, die einige Zeit in Anspruch nehmen können, z. B. beim Lesen von Dateien von der Festplatte. Hier macht der Begriff "Rückruf" den offensichtlichsten Sinn. Sobald ein E / A-Prozess gestartet wurde (z. B. das Lesen einer Datei von der Festplatte oder eines Servers, um Daten von einer http-Anforderung zurückzugeben), erfolgt eine asynchroneDas Programm wartet nicht darauf, dass es beendet wird. Es kann mit den als nächstes geplanten Aufgaben fortfahren und erst dann mit der benutzerdefinierten Funktionalität antworten, wenn benachrichtigt wurde, dass die Lesedatei oder die http-Anforderung abgeschlossen ist (oder fehlgeschlagen ist) und die Daten für die benutzerdefinierte Funktionalität verfügbar sind. Es ist, als würde man ein Unternehmen am Telefon anrufen und seine "Rückruf" -Nummer hinterlassen, damit es Sie anrufen kann, wenn jemand verfügbar ist, um sich bei Ihnen zu melden. Das ist besser, als lange an der Leitung zu bleiben und sich nicht um andere Angelegenheiten kümmern zu können.
Die asynchrone Verwendung umfasst von Natur aus einige Mittel zum Abhören des gewünschten Ereignisses (z. B. den Abschluss des E / A-Prozesses), sodass die benutzerdefinierte "Rückruf" -Funktionalität ausgeführt wird, wenn sie auftritt (und nur wenn sie auftritt). Im offensichtlichen AJAX-Beispiel wird, wenn die Daten tatsächlich vom Server ankommen, die Rückruffunktion ausgelöst, um diese Daten zum Ändern des DOM zu verwenden und daher das Browserfenster in diesem Umfang neu zu zeichnen.
Um es noch einmal zusammenzufassen. Einige Leute verwenden das Wort "Rückruf", um sich auf jede Art von benutzerdefinierter Funktionalität zu beziehen, die als Argument in eine vorhandene Funktion eingefügt werden kann. Aber zumindest für mich ist die am besten geeignete Verwendung des Wortes, wenn die injizierte "Rückruffunktion" asynchron verwendet wird - nur ausgeführt, wenn ein Ereignis eintritt, über das es darauf wartet, benachrichtigt zu werden.
quelle
Array.prototype.forEach()
und der Funktion, die als Argument übergeben wurdesetTimeout()
, und sie sind Pferde unterschiedlicher Farben, soweit Sie über Ihr Programm nachdenken .Für Nicht-Programmierer ist ein Rückruf ein Ausfüllen der Lücke in einem Programm.
Ein häufiger Punkt auf vielen Papierformularen ist "Person, die im Notfall angerufen werden muss". Dort ist eine leere Zeile. Sie schreiben den Namen und die Telefonnummer einer Person ein. Wenn ein Notfall eintritt, wird diese Person angerufen.
Das ist der Schlüssel. Sie ändern das Formular nicht (den Code, normalerweise den eines anderen). Sie können jedoch fehlende Informationen ( Ihre Nummer) eingeben .
Beispiel 1:
Rückrufe werden als angepasste Methoden verwendet, möglicherweise zum Hinzufügen / Ändern des Verhaltens eines Programms. Nehmen Sie zum Beispiel einen C-Code, der eine Funktion ausführt, aber nicht weiß, wie die Ausgabe gedruckt werden soll. Alles was es tun kann, ist eine Zeichenfolge zu erstellen. Wenn versucht wird, herauszufinden, was mit der Zeichenfolge zu tun ist, wird eine leere Zeile angezeigt. Aber der Programmierer gab Ihnen die Lücke, in die Sie Ihren Rückruf schreiben konnten!
In diesem Beispiel verwenden Sie keinen Bleistift, um eine Lücke auf einem Blatt Papier auszufüllen. Sie verwenden die Funktion
set_print_callback(the_callback)
.set_print_callback
ist der Bleistift,the_callback
sind Ihre Informationen, die Sie ausfüllen.Sie haben jetzt diese leere Zeile im Programm ausgefüllt. Wann immer die Ausgabe gedruckt werden muss, wird diese leere Zeile angezeigt und die dortigen Anweisungen befolgt (dh die dort eingegebene Funktion aufgerufen). Praktisch ermöglicht dies das Drucken auf dem Bildschirm, in einer Protokolldatei, auf einem Drucker. über eine Netzwerkverbindung oder eine beliebige Kombination davon. Sie haben die Lücke mit dem ausgefüllt, was Sie tun möchten.
Beispiel 2:
Wenn Sie erfahren, dass Sie eine Notrufnummer anrufen müssen, lesen Sie, was auf dem Papierformular steht, und rufen dann die gelesene Nummer an. Wenn diese Zeile leer ist, wird nichts unternommen.
Die GUI-Programmierung funktioniert ähnlich. Wenn Sie auf eine Schaltfläche klicken, muss das Programm herausfinden, was als Nächstes zu tun ist. Es geht und sucht nach dem Rückruf. Dieser Rückruf befindet sich in einem leeren Feld mit der Bezeichnung "Folgendes tun Sie, wenn Sie auf Button1 klicken".
Die meisten IDEs füllen die Lücke automatisch für Sie aus (schreiben Sie die grundlegende Methode), wenn Sie dazu aufgefordert werden (z
button1_clicked
. B. ). Dieses Leerzeichen kann jedoch jede Methode haben, die Sie verdammt gut mögen . Sie können die Methode aufrufenrun_computations
oderbutter_the_biscuits
solange Sie den Namen dieses Rückrufs in das richtige Leerzeichen einfügen. Sie können "555-555-1212" in die Notrufnummer eingeben. Es macht nicht viel Sinn, aber es ist zulässig.Letzte Anmerkung: Diese leere Zeile, die Sie mit dem Rückruf ausfüllen? Es kann nach Belieben gelöscht und neu geschrieben werden. (ob du solltest oder nicht, ist eine andere Frage, aber das ist ein Teil ihrer Macht)
quelle
Immer besser mit einem Beispiel beginnen :).
Angenommen, Sie haben zwei Module A und B.
Sie möchten, dass Modul A benachrichtigt wird, wenn ein Ereignis / eine Bedingung in Modul B auftritt. Modul B hat jedoch keine Ahnung von Ihrem Modul A. Es ist lediglich eine Adresse für eine bestimmte Funktion (von Modul A) über einen Funktionszeiger bekannt bereitgestellt von Modul A.
Alles, was B jetzt tun muss, ist ein "Rückruf" in Modul A, wenn ein bestimmtes Ereignis / eine bestimmte Bedingung mithilfe des Funktionszeigers auftritt. A kann innerhalb der Rückruffunktion weiterverarbeiten.
*) Ein klarer Vorteil hierbei ist, dass Sie alles über Modul A von Modul B abstrahieren. Modul B muss sich nicht darum kümmern, wer / was Modul A ist.
quelle
Johny, der Programmierer, braucht einen Hefter, also geht er zur Bürobedarfsabteilung und fragt nach einem. Nachdem er das Anforderungsformular ausgefüllt hat, kann er entweder dort stehen und warten, bis der Angestellte im Lager nach dem Hefter sucht (wie ein Anruf bei einer Sperrfunktion) ) oder mach in der Zwischenzeit etwas anderes.
Da dies normalerweise einige Zeit in Anspruch nimmt, stellt Johny zusammen mit dem Anfrageformular eine Notiz zusammen und bittet sie, ihn anzurufen, wenn der Hefter zur Abholung bereit ist, damit er in der Zwischenzeit etwas anderes tun kann, als auf seinem Schreibtisch ein Nickerchen zu machen.
quelle
Stellen Sie sich vor, Sie benötigen eine Funktion, die 10 Quadrat zurückgibt, damit Sie eine Funktion schreiben:
Später benötigen Sie 9 Quadrate, um eine weitere Funktion zu schreiben:
Schließlich werden Sie alle diese durch eine generische Funktion ersetzen:
Das gleiche Denken gilt für Rückrufe. Sie haben eine Funktion, die etwas tut, und wenn Sie fertig sind, rufen Sie doA auf:
Später möchten Sie, dass genau dieselbe Funktion doB aufruft, stattdessen können Sie die gesamte Funktion duplizieren:
Oder Sie können eine Rückruffunktion als Variable übergeben und müssen die Funktion nur einmal haben:
Dann müssen Sie nur noch compute (doA) und compute (doB) aufrufen.
Abgesehen von der Vereinfachung des Codes können Sie durch asynchronen Code wissen, dass der Vorgang abgeschlossen ist, indem Sie nach Abschluss Ihre beliebige Funktion aufrufen, ähnlich wie wenn Sie jemanden am Telefon anrufen und eine Rückrufnummer hinterlassen.
quelle
Sie fühlen sich krank und gehen zum Arzt. Er untersucht Sie und stellt fest, dass Sie Medikamente benötigen. Er verschreibt 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. Du gehst und holst es ab.
quelle
Es gibt zwei Punkte zu erklären: Zum einen die Funktionsweise eines Rückrufs (Weitergabe einer Funktion, die ohne Kenntnis des Kontexts aufgerufen werden kann) und zum anderen die asynchrone Behandlung von Ereignissen.
Die Analogie, auf das Eintreffen eines Pakets zu warten, das von anderen Antworten verwendet wurde, ist gut, um beide zu erklären. In einem Computerprogramm würden Sie den Computer anweisen, ein Paket zu erwarten. Normalerweise würde es jetzt dort sitzen und warten (und nichts anderes tun), bis das Paket ankommt, möglicherweise auf unbestimmte Zeit, wenn es nie ankommt. Für den Menschen klingt das albern, aber ohne weitere Maßnahmen ist dies für einen Computer völlig natürlich.
Jetzt wäre der Rückruf die Glocke an Ihrer Haustür. Sie bieten dem Paketservice die Möglichkeit, Sie über die Ankunft des Pakets zu informieren, ohne dass dieser wissen muss, wo (auch wenn) Sie sich im Haus befinden oder wie die Glocke funktioniert. (Zum Beispiel senden einige "Glocken" tatsächlich einen Anruf aus.) Da Sie eine "Rückruffunktion" bereitgestellt haben, die jederzeit außerhalb des Kontexts "aufgerufen" werden kann, können Sie jetzt aufhören, auf der Veranda zu sitzen, und "das erledigen" Ereignis "(der Paketankunft) wann immer es Zeit ist.
quelle
Stellen Sie sich vor, eine Freundin verlässt Ihr Haus und Sie sagen ihr: "Rufen Sie mich an, wenn Sie nach Hause kommen, damit ich weiß, dass Sie sicher angekommen sind." das ist (buchstäblich) ein Rückruf . Das ist eine Rückruffunktion, unabhängig von der Sprache. Sie möchten, dass eine Prozedur die Kontrolle an Sie zurückgibt, wenn sie eine Aufgabe abgeschlossen hat, und geben ihr eine Funktion, mit der Sie zurückgerufen werden können.
In Python zum Beispiel
grabDBValue
könnte so geschrieben werden, dass nur ein Wert aus einer Datenbank abgerufen wird und Sie dann angeben können, was mit dem Wert tatsächlich geschehen soll, sodass eine Funktion akzeptiert wird. Sie wissen nicht, wann oder ob SiegrabDBValue
zurückkehren werden, aber wenn / wann dies der Fall ist, wissen Sie, was Sie möchten. Hier übergebe ich eine anonyme Funktion (oder Lambda ), die den Wert an ein GUI-Fenster sendet. Ich könnte das Verhalten des Programms leicht ändern, indem ich dies tue:Rückrufe funktionieren gut in Sprachen, in denen Funktionen erstklassige Werte sind, genau wie die üblichen Ganzzahlen, Zeichenfolgen, Booleschen Werte usw. In C können Sie eine Funktion "übergeben", indem Sie einen Zeiger darauf übergeben, und der Aufrufer kann dies verwenden. In Java fragt der Aufrufer nach einer statischen Klasse eines bestimmten Typs mit einem bestimmten Methodennamen, da es außerhalb der Klassen keine Funktionen ("Methoden") gibt. und in den meisten anderen dynamischen Sprachen können Sie einfach eine Funktion mit einfacher Syntax übergeben.
Protip:
In Sprachen mit lexikalischem Umfang (wie Scheme oder Perl) können Sie einen Trick wie folgt ausführen :
$val
In diesem Fall6
hat der Rückruf Zugriff auf die Variablen, die in der lexikalischen Umgebung deklariert wurden, in der er definiert wurde. Lexikalischer Umfang und anonyme Rückrufe sind eine leistungsstarke Kombination, die dem unerfahrenen Programmierer weitere Studien rechtfertigt.quelle
Sie haben Code, den Sie ausführen möchten. Wenn Sie es aufrufen, warten Sie normalerweise darauf, dass es fertig ist, bevor Sie fortfahren (was dazu führen kann, dass Ihre App grau wird / eine Drehzeit für einen Cursor erzeugt).
Eine alternative Methode besteht darin, diesen Code parallel auszuführen und mit Ihrer eigenen Arbeit fortzufahren. Aber was ist, wenn Ihr ursprünglicher Code abhängig von der Antwort des aufgerufenen Codes unterschiedliche Aufgaben ausführen muss? In diesem Fall können Sie den Namen / Speicherort des Codes eingeben, den er aufrufen soll, wenn er fertig ist. Dies ist ein "Rückruf".
Normaler Code: Fragen Sie nach Informationen-> Prozessinformationen-> Verarbeiten Sie die Ergebnisse der Verarbeitung-> Fahren Sie mit anderen Dingen fort.
Bei Rückrufen: Fragen Sie nach Informationen-> Prozessinformationen-> Fahren Sie mit anderen Dingen fort. Und zu einem späteren Zeitpunkt-> Behandeln Sie die Ergebnisse der Verarbeitung.
quelle
Ohne Rückruf weder andere spezielle Programmierressourcen (wie Threading und andere) ist ein Programm genau eine Folge von Anweisungen, die nacheinander ausgeführt werden , und selbst mit einer Art "dynamischem Verhalten", das durch bestimmte Bedingungen bestimmt wird, alle möglichen Szenarien muss vorher programmiert sein .
Wenn wir also einem Programm ein wirklich dynamisches Verhalten verleihen müssen, können wir einen Rückruf verwenden. Mit Callback können Sie durch Parameter anweisen, ein Programm ein anderes Programm aufzurufen, das einige zuvor definierte Parameter bereitstellt, und einige Ergebnisse erwarten ( dies ist die Vertrags- oder Operationssignatur ), sodass diese Ergebnisse von einem Drittanbieterprogramm erzeugt / verarbeitet werden können, das nicht vorhanden war ist bisher nicht bekannt.
Diese Technik ist die Grundlage des Polymorphismus, der auf Programme, Funktionen, Objekte und alle anderen von Computern ausgeführten Codeeinheiten angewendet wird.
Die menschliche Welt, die als Beispiel für den Rückruf verwendet wird, wird schön erklärt, wenn Sie einen Job machen. Nehmen wir an, Sie sind Maler ( hier sind Sie das Hauptprogramm, das malt ) und rufen Sie Ihren Kunden manchmal an, um ihn zu bitten, das Ergebnis Ihres Jobs zu genehmigen Daher entscheidet er, ob das Bild gut ist ( Ihr Kunde ist das Programm eines Drittanbieters ).
Im obigen Beispiel sind Sie Maler und "delegieren" den Auftrag an andere, um das Ergebnis zu genehmigen. Das Bild ist der Parameter, und jeder neue Kunde (die zurückgerufene "Funktion") ändert das Ergebnis Ihrer Arbeit und entscheidet, was er will über das Bild ( die Entscheidung der Kunden ist das zurückgegebene Ergebnis der "Rückruffunktion" ).
Ich hoffe, diese Erklärung kann nützlich sein.
quelle
Stellen wir uns vor, Sie würden mir eine möglicherweise langfristige Aufgabe geben: Erhalten Sie die Namen der ersten fünf einzigartigen Personen, denen Sie begegnen. Dies kann Tage dauern, wenn ich mich in einem dünn besiedelten Gebiet befinde. Sie sind nicht wirklich daran interessiert, auf Ihren Händen zu sitzen, während ich herumlaufe. Sie sagen also: "Wenn Sie die Liste haben, rufen Sie mich in meinem Handy an und lesen Sie sie mir vor. Hier ist die Nummer."
Sie haben mir eine Rückrufreferenz gegeben - eine Funktion, die ich ausführen soll, um die weitere Verarbeitung abzugeben.
In JavaScript könnte es ungefähr so aussehen:
Dies könnte wahrscheinlich in vielerlei Hinsicht verbessert werden. Sie können beispielsweise einen zweiten Rückruf bereitstellen: Wenn dies länger als eine Stunde dauert, rufen Sie das rote Telefon an und teilen Sie der antwortenden Person mit, dass Sie eine Zeitüberschreitung haben.
quelle
Rückrufe lassen sich am einfachsten anhand des Telefonsystems beschreiben. Ein Funktionsaufruf ist analog dazu, jemanden am Telefon anzurufen, ihr eine Frage zu stellen, eine Antwort zu erhalten und aufzulegen. Durch Hinzufügen eines Rückrufs wird die Analogie geändert, sodass Sie ihr nach dem Stellen einer Frage auch Ihren Namen und Ihre Nummer geben, damit sie Sie mit der Antwort zurückrufen kann. - Paul Jakubik, "Callback-Implementierungen in C ++"
quelle
Ein Rückruf ist eine Funktion, die von einer zweiten Funktion aufgerufen wird. Diese zweite Funktion weiß nicht im Voraus, welche Funktion sie aufruft. Die Identität der Rückruffunktion wird also irgendwo gespeichert oder als Parameter an die zweite Funktion übergeben. Diese "Identität" kann abhängig von der Programmiersprache die Adresse des Rückrufs oder eine andere Art von Zeiger oder der Name der Funktion sein. Der Principal ist derselbe. Wir speichern oder übergeben einige Informationen, die die Funktion eindeutig identifizieren.
Wenn es soweit ist, kann die zweite Funktion den Rückruf aufrufen und abhängig von den Umständen in diesem Moment Parameter bereitstellen. Möglicherweise wird der Rückruf sogar aus einer Reihe möglicher Rückrufe ausgewählt. Die Programmiersprache muss eine Art Syntax bereitstellen, damit die zweite Funktion den Rückruf aufrufen kann, wobei ihre "Identität" bekannt ist.
Dieser Mechanismus hat sehr viele Verwendungsmöglichkeiten. Bei Rückrufen kann der Designer einer Funktion die Anpassung vornehmen, indem er die bereitgestellten Rückrufe aufruft. Beispielsweise kann eine Sortierfunktion einen Rückruf als Parameter verwenden, und dieser Rückruf kann eine Funktion zum Vergleichen zweier Elemente sein, um zu entscheiden, welches zuerst kommt.
Übrigens kann abhängig von der Programmiersprache das Wort "Funktion" in der obigen Diskussion durch "Block", "Schließung", "Lambda" usw. ersetzt werden.
quelle
Normalerweise haben wir Variablen an Funktionen gesendet. Angenommen, Sie haben eine Aufgabe, bei der die Variable verarbeitet werden muss, bevor sie als Argument angegeben wird. Sie können den Rückruf verwenden.
function1(var1, var2)
ist der übliche Weg.Was ist, wenn ich
var2
verarbeitet und dann als Argument gesendet werden möchte ?function1(var1, function2(var2))
Dies ist eine Art von Rückruf, bei dem
function2
Code ausgeführt und eine Variable an die ursprüngliche Funktion zurückgegeben wird.quelle
Eine metaphorische Erklärung:
Ich habe ein Paket, das ich an einen Freund liefern möchte, und ich möchte auch wissen, wann mein Freund es erhält.
Also bringe ich das Paket zur Post und bitte sie, es zu liefern. Wenn ich wissen möchte, wann mein Freund das Paket erhält, habe ich zwei Möglichkeiten:
(a) Ich kann bei der Post warten, bis es zugestellt wird.
(b) Ich werde eine E-Mail erhalten, wenn sie zugestellt wird.
Option (b) ist analog zu einem Rückruf.
quelle
Um Rückrufe zu lehren, müssen Sie zuerst den Zeiger lehren. Sobald die Schüler die Idee des Zeigers auf eine Variable verstanden haben, wird die Idee von Rückrufen einfacher. Angenommen, Sie verwenden C / C ++, können diese Schritte ausgeführt werden.
Es könnte noch viel mehr Dinge geben. Beziehen Sie die Schüler ein und sie werden es entdecken. Hoffe das hilft.
quelle
Im Klartext ist ein Rückruf ein Versprechen. Joe, Jane, David und Samantha teilen sich eine Fahrgemeinschaft, um zu arbeiten. Joe fährt heute. Jane, David und Samantha haben mehrere Möglichkeiten:
Option 1: Dies ist eher ein Umfragebeispiel, bei dem Jane in einer "Schleife" stecken bleibt und prüft, ob Joe draußen ist. Jane kann in der Zwischenzeit nichts anderes tun.
Option 2: Dies ist das Rückrufbeispiel. Jane fordert Joe auf, an der Tür zu klingeln, wenn er draußen ist. Sie gibt ihm eine "Funktion", um die Türklingel zu läuten. Joe muss nicht wissen, wie die Türklingel funktioniert oder wo sie ist, er muss nur diese Funktion aufrufen, dh die Türklingel läuten, wenn er dort ist.
Rückrufe werden durch "Ereignisse" ausgelöst. In diesem Beispiel ist das "Ereignis" Joes Ankunft. In Ajax können Ereignisse beispielsweise "Erfolg" oder "Misserfolg" der asynchronen Anforderung sein und jeder kann den gleichen oder unterschiedliche Rückrufe haben.
In Bezug auf JavaScript-Anwendungen und Rückrufe. Wir müssen auch "Schließungen" und den Anwendungskontext verstehen. Worauf sich "dies" bezieht, kann JavaScript-Entwickler leicht verwirren. In diesem Beispiel gibt es innerhalb der Methode / des Rückrufs "ring_the_door_bell ()" jeder Person möglicherweise einige andere Methoden, die jede Person basierend auf ihrer morgendlichen Routine ausführen muss. "Schalte den Fernseher aus()". Wir möchten, dass sich "dies" auf das "Jane" -Objekt oder das "David" -Objekt bezieht, damit jeder das einrichten kann, was er sonst noch tun muss, bevor Joe sie aufnimmt. Hier muss für das Einrichten des Rückrufs mit Joe die Methode parodiert werden, damit sich "this" auf das richtige Objekt bezieht.
Ich hoffe, das hilft!
quelle
Ein Rückruf ist ein an sich selbst adressierter Briefumschlag. Wenn Sie eine Funktion aufrufen, ist das wie das Senden eines Briefes. Wenn Sie möchten, dass diese Funktion eine andere Funktion aufruft, geben Sie diese Informationen in Form einer Referenz oder Adresse an.
quelle
Ich denke, es ist eine ziemlich einfache Aufgabe zu erklären.
Beim ersten Rückruf handelt es sich nur um gewöhnliche Funktionen.
Und das weitere ist, dass wir diese Funktion (nennen wir sie A) aus einer anderen Funktion heraus (nennen wir sie B) aufrufen.
Das Magische daran ist, dass ich entscheide, welche Funktion von der Funktion von außen aufgerufen werden soll B
Zum Zeitpunkt, an dem ich die Funktion BI schreibe, weiß ich nicht, welche Rückruffunktion aufgerufen werden soll. Zu dem Zeitpunkt, an dem ich die Funktion BI aufrufe, muss diese Funktion auch die Funktion A aufrufen. Das ist alles.
quelle
Was ist eine Rückruffunktion?
Die einfache Antwort auf diese erste Frage lautet, dass eine Rückruffunktion eine Funktion ist, die über einen Funktionszeiger aufgerufen wird. Wenn Sie den Zeiger (die Adresse) einer Funktion als Argument an eine andere übergeben, wird beim Aufrufen der Funktion, auf die dieser Zeiger verweist, darauf hingewiesen, dass ein Rückruf erfolgt.
Die Rückruffunktion ist schwer zu verfolgen, aber manchmal sehr nützlich. Besonders wenn Sie Bibliotheken entwerfen. Die Rückruffunktion entspricht der Aufforderung an Ihren Benutzer, Ihnen einen Funktionsnamen zu geben, und Sie rufen diese Funktion unter bestimmten Bedingungen auf.
Beispielsweise schreiben Sie einen Rückruf-Timer. Hier können Sie die Dauer und die aufzurufende Funktion angeben, und die Funktion wird entsprechend zurückgerufen. "Führen Sie myfunction () 5 Mal alle 10 Sekunden aus."
Sie können auch ein Funktionsverzeichnis erstellen, eine Liste mit Funktionsnamen übergeben und die Bibliothek auffordern, einen entsprechenden Rückruf durchzuführen. "Rückruf erfolgreich () wenn erfolgreich, Rückruf fehlgeschlagen () wenn fehlgeschlagen."
Schauen wir uns ein einfaches Beispiel für einen Funktionszeiger an
Wie übergebe ich ein Argument an die Rückruffunktion?
Es wurde beobachtet, dass der Funktionszeiger zum Implementieren eines Rückrufs void * enthält, was darauf hinweist, dass er jede Art von Variable einschließlich Struktur aufnehmen kann. Daher können Sie mehrere Argumente nach Struktur übergeben.
quelle
Ein Rückruf ist eine Methode, deren Ausführung geplant ist, wenn eine Bedingung erfüllt ist.
Ein Beispiel aus der "realen Welt" ist ein lokaler Videospielladen. Sie warten auf Half-Life 3. Anstatt jeden Tag in den Laden zu gehen, um zu sehen, ob es in ist, registrieren Sie Ihre E-Mail in einer Liste, um benachrichtigt zu werden, wenn das Spiel verfügbar ist. Die E-Mail wird zu Ihrem "Rückruf" und die Bedingung, die erfüllt werden muss, ist die Verfügbarkeit des Spiels.
Ein Beispiel für "Programmierer" ist eine Webseite, auf der Sie eine Aktion ausführen möchten, wenn Sie auf eine Schaltfläche klicken. Sie registrieren eine Rückrufmethode für eine Schaltfläche und führen andere Aufgaben aus. Wenn der Benutzer auf die Schaltfläche klickt, zeigt der Browser die Liste der Rückrufe für dieses Ereignis an und ruft Ihre Methode auf.
Ein Rückruf ist eine Möglichkeit, Ereignisse asynchron zu behandeln. Sie können nie wissen, wann der Rückruf ausgeführt wird oder ob er überhaupt ausgeführt wird. Der Vorteil ist, dass Ihr Programm und Ihre CPU-Zyklen frei sind, um andere Aufgaben auszuführen, während Sie auf die Antwort warten.
quelle
Schlicht und einfach: Ein Rückruf ist eine Funktion, die Sie einer anderen Funktion geben, damit diese aufgerufen werden kann.
Normalerweise wird es aufgerufen, wenn ein Vorgang abgeschlossen ist. Da Sie den Rückruf erstellen, bevor Sie ihn der anderen Funktion übergeben, können Sie ihn mit Kontextinformationen von der Aufrufseite initialisieren. Aus diesem Grund wird es als Rückruf * zurück * bezeichnet - die erste Funktion ruft den Kontext zurück, von dem aus sie aufgerufen wurde.
quelle
„In der Computerprogrammierung ist ein Rückruf eine Referenz auf ausführbaren Code oder einen ausführbaren Code, der als Argument an anderen Code übergeben wird. Auf diese Weise kann eine untergeordnete Softwareschicht eine Unterroutine (oder Funktion) aufrufen, die in einer übergeordneten Ebene definiert ist. “ - Wikipedia
Rückruf in C mit Funktionszeiger
In C wird der Rückruf mit dem Funktionszeiger implementiert. Funktionszeiger - ist, wie der Name schon sagt, ein Zeiger auf eine Funktion.
Zum Beispiel int (* ptrFunc) ();
Hier ist ptrFunc ein Zeiger auf eine Funktion, die keine Argumente akzeptiert und eine Ganzzahl zurückgibt. Vergessen Sie NICHT, in Klammern zu setzen, sonst geht der Compiler davon aus, dass ptrFunc ein normaler Funktionsname ist, der nichts nimmt und einen Zeiger auf eine Ganzzahl zurückgibt.
Hier ist ein Code zur Demonstration des Funktionszeigers.
Versuchen wir nun, das Konzept des Rückrufs in C mithilfe des Funktionszeigers zu verstehen.
Das vollständige Programm enthält drei Dateien: callback.c, reg_callback.h und reg_callback.c.
Wenn wir dieses Programm ausführen, wird die Ausgabe sein
Dies ist ein Programm, das den Funktionsrückruf in register_callback in my_callback zurück im Hauptprogramm demonstriert
Die Funktion der höheren Schicht ruft eine Funktion der niedrigeren Schicht als normalen Aufruf auf, und der Rückrufmechanismus ermöglicht es der Funktion der unteren Schicht, die Funktion der höheren Schicht über einen Zeiger auf eine Rückruffunktion aufzurufen.
Rückruf in Java über die Schnittstelle
Java hat nicht das Konzept eines Funktionszeigers. Es implementiert den Rückrufmechanismus über seinen Schnittstellenmechanismus. Hier deklarieren wir anstelle eines Funktionszeigers eine Schnittstelle mit einer Methode, die aufgerufen wird, wenn der Angerufene seine Aufgabe beendet
Lassen Sie es mich anhand eines Beispiels demonstrieren:
Die Rückrufschnittstelle
Der Anrufer oder die höhere Klasse
Die Callee oder die untere Schichtfunktion
Rückruf mit EventListener-Muster
Dieses Muster wird verwendet, um 0 bis n Anzahlen von Beobachtern / Zuhörern zu benachrichtigen, dass eine bestimmte Aufgabe beendet wurde
Der Unterschied zwischen dem Rückrufmechanismus und dem EventListener / Observer-Mechanismus besteht darin, dass der Angerufene beim Rückruf den einzelnen Anrufer benachrichtigt, während der Angerufene bei Eventlisener / Observer jeden benachrichtigen kann, der an diesem Ereignis interessiert ist (die Benachrichtigung kann an einige andere Teile des Anwendung, die die Aufgabe nicht ausgelöst hat)
Lassen Sie es mich anhand eines Beispiels erklären.
Die Ereignisschnittstelle
Klassen-Widget
Klassenschaltfläche
Klassen-Kontrollkästchen
Aktivitätsklasse
Paket com.som_itsolutions.training.java.exampleeventlistener;
Andere Klasse
Hauptklasse
Wie Sie dem obigen Code entnehmen können, haben wir eine Schnittstelle namens events, die im Grunde alle Ereignisse auflistet, die für unsere Anwendung auftreten können. Die Widget-Klasse ist die Basisklasse für alle UI-Komponenten wie Button, Checkbox. Diese UI-Komponenten sind die Objekte, die die Ereignisse tatsächlich vom Framework-Code empfangen. Die Widget-Klasse implementiert die Ereignisschnittstelle und verfügt außerdem über zwei verschachtelte Schnittstellen, nämlich OnClickEventListener und OnLongClickEventListener
Diese beiden Schnittstellen sind für das Abhören von Ereignissen verantwortlich, die auf den vom Widget abgeleiteten UI-Komponenten wie Button oder Checkbox auftreten können. Wenn wir dieses Beispiel mit dem früheren Callback-Beispiel unter Verwendung der Java-Schnittstelle vergleichen, fungieren diese beiden Schnittstellen als Callback-Schnittstelle. Der übergeordnete Code (Here Activity) implementiert diese beiden Schnittstellen. Und wenn ein Ereignis in einem Widget auftritt, wird der Code auf höherer Ebene (oder die Methode dieser Schnittstellen, die im Code auf höherer Ebene implementiert ist, der hier Aktivität ist) aufgerufen.
Lassen Sie mich nun den grundlegenden Unterschied zwischen Callback- und Eventlistener-Muster diskutieren. Wie bereits erwähnt, kann der Callee mit Callback nur einen einzigen Anrufer benachrichtigen. Im Fall eines EventListener-Musters kann sich jedoch jeder andere Teil oder jede andere Klasse der Anwendung für die Ereignisse registrieren, die auf der Schaltfläche oder dem Kontrollkästchen auftreten können. Das Beispiel für diese Art von Klasse ist die OtherClass. Wenn Sie den Code der OtherClass sehen, werden Sie feststellen, dass sie sich als Listener für das ClickEvent registriert hat, das in der in der Aktivität definierten Schaltfläche auftreten kann. Interessant ist, dass neben der Aktivität (dem Anrufer) auch diese andere Klasse benachrichtigt wird, wenn das Klickereignis auf der Schaltfläche auftritt.
quelle
Mit Callbacks können Sie Ihren eigenen Code in einen anderen Codeblock einfügen, der zu einem anderen Zeitpunkt ausgeführt werden soll. Dadurch wird das Verhalten dieses anderen Codeblocks an Ihre Anforderungen angepasst oder ergänzt. Sie erhalten Flexibilität und Anpassbarkeit, während Sie in der Lage sind, mehr wartbaren Code zu haben.
Weniger Hardcode = einfacher zu warten und zu ändern = weniger Zeit = mehr Geschäftswert = Attraktivität.
In Javascript können Sie beispielsweise mit Underscore.js alle geraden Elemente in einem Array wie dem folgenden finden:
Beispiel mit freundlicher Genehmigung von Underscore.js: http://documentcloud.github.com/underscore/#filter
quelle
[bearbeitet] Wenn wir zwei Funktionen haben, sagen wir FunktionA und FunktionB , wenn Funktioneine abhängt FunktionD .
dann rufen wir functionB als Rückruffunktion auf. Dies wird im Spring-Framework häufig verwendet.
quelle
Stellen Sie sich eine Methode vor, die einem Mitarbeiter eine Aufgabe gibt. Eine einfache Aufgabe könnte folgende sein:
Ihr Mitarbeiter rechnet fleißig und gibt Ihnen folgendes Ergebnis:
Aber Ihr Mitarbeiter hat ein Problem, er versteht Notationen nicht immer, wie
^
, aber er versteht sie anhand ihrer Beschreibung. Wie zum Beispielexponent
. Jedes Mal, wenn er eines davon findet, erhalten Sie Folgendes zurück:Dazu müssen Sie Ihren gesamten Befehlssatz erneut schreiben, nachdem Sie Ihrem Kollegen erklärt haben, was der Charakter bedeutet, und er erinnert sich nicht immer zwischen den Fragen. Und er hat Schwierigkeiten, sich auch an Ihre Tipps zu erinnern, wie zum Beispiel mich einfach zu fragen. Er folgt jedoch immer Ihren schriftlichen Anweisungen, so gut er kann.
Wenn Sie an eine Lösung denken, fügen Sie einfach allen Ihren Anweisungen Folgendes hinzu:
Wenn er jetzt ein Problem hat, ruft er Sie an und fragt, anstatt Ihnen eine schlechte Antwort zu geben und den Prozess neu zu starten.
quelle
Dies davon in Bezug auf das Herunterladen einer Webseite:
Ihr Programm läuft auf einem Mobiltelefon und fordert die Webseite http://www.google.com an . Wenn Sie Ihr Programm synchron schreiben, wird die Funktion, die Sie zum Herunterladen der Daten schreiben, kontinuierlich ausgeführt, bis alle Daten heruntergeladen sind. Dies bedeutet, dass Ihre Benutzeroberfläche nicht aktualisiert wird und grundsätzlich eingefroren erscheint. Wenn Sie Ihr Programm mit Rückrufen schreiben, fordern Sie die Daten an und sagen "Führen Sie diese Funktion aus, wenn Sie fertig sind." Auf diese Weise kann die Benutzeroberfläche weiterhin Benutzerinteraktionen zulassen, während die Datei heruntergeladen wird. Sobald der Download der Webseite abgeschlossen ist, wird Ihre Ergebnisfunktion (Rückruf) aufgerufen und Sie können die Daten verarbeiten.
Grundsätzlich können Sie etwas anfordern und die Ausführung fortsetzen, während Sie auf das Ergebnis warten. Sobald das Ergebnis über eine Rückruffunktion bei Ihnen eingeht, können Sie den Vorgang dort fortsetzen, wo er aufgehört hat.
quelle