Comment expliquer en langage clair, les rappels ? Comment sont-ils différents d’appeler une fonction depuis une autre fonction qui prend peu de contexte de l’appel de la fonction ? Comment peut-on expliquer leur pouvoir à un programmeur novice ?
Réponses
Trop de publicités?Je vais essayer de garder cette mort simple. Un "rappel" est une fonction qui est appelée par une autre fonction qui prend la première fonction en tant que paramètre. Beaucoup de temps, un "rappel" est une fonction qui est appelée lorsque quelque chose se passe. Que quelque chose peut être appelé un "événement" dans le programmeur-parler.
Imaginez ce scénario: Vous attendez un colis dans un couple des jours. Le paquet est un cadeau pour votre voisin. Par conséquent, une fois que vous obtenez le paquet, vous voulez qu'il introduit sur la les voisins. Vous êtes hors de la ville, et si vous laissez des instructions pour votre conjoint.
Vous pourriez lui dire d'aller chercher le colis et de le mettre en voisins. Si votre conjoint était aussi stupide qu'un ordinateur, elle allait s'asseoir à la porte et attendre que le paquet jusqu'à ce qu'il est venu (NE RIEN FAIRE d'AUTRE) et puis une fois qu'il est venu, elle serait plus pour les voisins. Mais il y a une meilleure façon. Dites à votre femme que une FOIS, elle reçoit le paquet, elle devrait l'amener sur les voisins. Ensuite, elle peut aller sur la vie normalement JUSQU'à ce qu'elle reçoit le colis.
Dans notre exemple, la réception du paquet est "l'événement" et l'amener à la les voisins est le "rappel". Votre femme "runs" vos instructions pour mettre le paquet sur seulement lorsque le colis arrive. Beaucoup mieux!
Ce genre de pensée est évidente dans la vie quotidienne, mais les ordinateurs n'ont pas la même sorte de sens commun. Examiner comment normalement, les programmeurs d'écrire dans un fichier:
fileObject = open(file)
# now that we have WAITED for the file to open, we can write to it
fileObject.write("We are writing to the file.")
# now we can continue doing the other, totally unrelated things our program does
Ici, nous attendons pour le fichier à ouvrir, avant de nous écrire. Cette "bloque" le flux d'exécution, et notre programme ne peut pas faire les autres choses qu'il pourrait avoir besoin pour faire! Et si l'on pouvait faire ceci à la place:
# we pass writeToFile (A CALLBACK FUNCTION!) to the open function
fileObject = open(file, writeToFile)
# execution continues flowing -- we don't wait for the file to be opened
# ONCE the file is opened we write to it, but while we wait WE CAN DO OTHER THINGS!
Il s'avère que nous pouvons faire cela avec certaines langues et des cadres. C'est plutôt cool! Découvrez Node.js pour obtenir une certaine pratique réelle, avec ce genre de pensée.
Souvent, une application doit exécuter les différentes fonctions sur la base de son contexte et de l'état. Pour cela, nous utilisons une variable où l'on stocke les informations au sujet de la fonction à appeler. Selon son besoin, l'application permettra de définir cette variable avec les informations sur la fonction à appeler et appeler la fonction en utilisant la même variable.
En javascript, l'exemple ci-dessous. Ici, nous utilisons un argument de méthode comme une variable où nous stockons des informations au sujet de la fonction.
function processArray(arr, callback) {
var resultArr = new Array();
for (var i = arr.length-1; i >= 0; i--)
resultArr[i] = callback(arr[i]);
return resultArr;
}
var arr = [1, 2, 3, 4];
var arrReturned = processArray(arr, function(arg) {return arg * -1;});
// arrReturned would be [-1, -2, -3, -4]
Comment expliquer les rappels en anglais?
En clair, une fonction de rappel est comme un Travailleur qui "demande de retour" à son Manager quand il a terminé une Tâche.
Comment sont-ils différents de l'appel d'une fonction à partir d'une autre fonction en prenant le contexte de l'appel de la fonction?
Il est vrai que vous appelez une fonction dans une autre fonction, mais l'essentiel est que le rappel est traité comme un Objet, de sorte que vous pouvez changer la Fonction d'appel en fonction de l'état du système (telles que la Stratégie Design Pattern).
Comment peut leur puissance d'être expliqué pour un débutant programmeur?
La puissance de callbacks peuvent facilement être vu dans le style AJAX sites web qui ont besoin d'extraire des données à partir d'un serveur. Télécharger les nouvelles données peut prendre un certain temps. Sans rappels, l'ensemble de votre Interface Utilisateur "gèle" alors que le téléchargement de nouvelles données, ou vous auriez besoin de rafraîchir la page entière plutôt qu'en partie seulement. Avec un rappel, vous pouvez insérer un "chargement" de l'image et de la remplacer par les nouvelles données une fois qu'il est chargé.
Certains codes sans un rappel:
function grabAndFreeze() { showNowLoading(true); var jsondata = getData('http://yourserver.com/data/messages.json'); /* User Interface 'freezes' while getting data */ processData(jsondata); showNowLoading(false); do_other_stuff(); // not called until data fully downloaded } function processData(jsondata) { // do something with the data var count = jsondata.results ? jsondata.results.length : 0; $('#counter_messages').text(['Fetched', count, 'new items'].join(' ')); $('#results_messages').html(jsondata.results || '(no new messages)'); }
Avec De Rappel:
Voici un exemple avec une fonction de rappel, à l'aide de jQuery getJSON:
function processDataCB(jsondata) { // callback: update UI with results showNowLoading(false); var count = jsondata.results ? jsondata.results.length : 0; $('#counter_messages').text(['Fetched', count, 'new items'].join(' ')); $('#results_messages').html(jsondata.results || '(no new messages)'); } function grabAndGo() { // and don't freeze showNowLoading(true); $('#results_messages').html(now_loading_image); $.getJSON("http://yourserver.com/data/messages.json", processDataCB); /* Call processDataCB when data is downloaded, no frozen User Interface! */ do_other_stuff(); // called immediately }
Avec La Fermeture:
Souvent la fonction de rappel doit accéder
state
de la fonction d'appel à l'aide d'unclosure
, qui est comme le Travailleur besoin d'obtenir des informations à partir du Gestionnaire avant qu'il ne puisse terminer sa Tâche. Pour créer l'closure
, vous pouvez inline la fonction de sorte qu'il voit les données dans le contexte de l'appel:/* Grab messages, chat users, etc by changing dtable. Run callback cb when done.*/ function grab(dtable, cb) { if (null == dtable) { dtable = "messages"; } var uiElem = "_" + dtable; showNowLoading(true, dtable); $('#results' + uiElem).html(now_loading_image); $.getJSON("http://yourserver.com/user/"+dtable+".json", cb || function (jsondata) { // Using a closure: can "see" dtable argument and uiElem variables above. var count = jsondata.results ? jsondata.results.length : 0, counterMsg = ['Fetched', count, 'new', dtable].join(' '), // no new chatters/messages/etc defaultResultsMsg = ['(no new ', dtable, ')'].join(''); showNowLoading(false, dtable); $('#counter' + uiElem).text(counterMsg); $('#results'+ uiElem).html(jsondata.results || defaultResultsMsg); }); /* User Interface calls cb when data is downloaded */ do_other_stuff(); // called immediately }
Utilisation:
// update results_chatters when chatters.json data is downloaded: grab("chatters"); // update results_messages when messages.json data is downloaded grab("messages"); // call myCallback(jsondata) when "history.json" data is loaded: grab("history", myCallback);
Fermeture
Enfin, voici une définition de l'
closure
de Douglas Crockford:Les fonctions peuvent être définies à l'intérieur d'autres fonctions. La fonction interne a accès à la rva et des paramètres de la fonction externe. Si une référence à une fonction interne survit (par exemple, une fonction de rappel), à l'extérieur de la fonction de vars aussi survivre.
Voir aussi:
Toujours mieux de commencer avec un exemple :).
Supposons que vous avez deux modules A et B.
Vous voulez Un module pour être notifié quand un événement/état se produit dans le module B. Cependant, le module B n'a aucune idée au sujet de votre module A. Tous les il connaît, c'est une adresse à une fonction particulière (module A), par l'intermédiaire d'un pointeur de fonction qui est fourni par le module A.
Donc, tous les B a à faire maintenant, c'est "rappel" dans le module A, lorsqu'un événement particulier/condition se produit en utilisant le pointeur de fonction. Un peut poursuivre le traitement à l'intérieur de la fonction de rappel.
*) Un net avantage ici est que vous êtes dans l'abstraction tout sur Un module de module B. Module B n'ont pas à se préoccuper de qui/de quoi module A est.
Johny le programmeur a besoin d'une agrafeuse, donc, il va vers le bas de la fourniture de bureau et demandez une pour une, après avoir rempli le formulaire de demande, il peut soit rester là et attendre que le greffier aller chercher autour de l'entrepôt pour l'agrafeuse (comme une fonction de blocage d'appel) ou aller faire autre chose entre temps.
car généralement, cela prend du temps, johny met une note avec le formulaire de requête lui demandant de l'appeler quand l'agrafeuse est prêt pour le ramassage, donc, entre-temps, il peut aller faire autre chose comme faire la sieste sur son bureau.