open - javascript callback function with parameters




Comment expliquer les rappels en anglais? En quoi sont-ils différents d'appeler une fonction d'une autre fonction? (20)

Comment expliquer les rappels en anglais? En quoi sont-ils différents d'appeler une fonction d'une autre fonction en prenant un certain contexte à partir de la fonction d'appel? Comment leur pouvoir peut-il être expliqué à un programmeur débutant?


Comment expliquer les rappels en anglais?

En clair, une fonction de rappel est semblable à un travailleur qui «rappelle» son gestionnaire lorsqu'il a terminé une tâche .

En quoi sont-ils différents d'appeler une fonction d'une autre fonction en prenant un certain contexte à partir de la fonction d'appel?

Il est vrai que vous appelez une fonction d'une autre fonction, mais la clé est que le rappel est traité comme un objet, vous pouvez donc changer quelle fonction appeler en fonction de l'état du système (comme le modèle de conception de stratégie).

Comment leur pouvoir peut-il être expliqué à un programmeur débutant?

Le pouvoir des rappels peut facilement être vu dans les sites Web de style AJAX qui ont besoin de tirer des données d'un serveur. Le téléchargement des nouvelles données peut prendre un certain temps. Sans rappels, toute votre interface utilisateur se "gèle" pendant le téléchargement des nouvelles données, ou vous devez actualiser la page entière plutôt qu'une partie de celle-ci. Avec un callback, vous pouvez insérer une image "now loading" et la remplacer par les nouvelles données une fois qu'elle est chargée.

Du code sans 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 rappel:

Voici un exemple avec un rappel, en utilisant getJSON de jQuery:

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 fermeture:

Le rappel doit souvent accéder à l' state partir de la fonction d'appel à l'aide d'une closure , ce qui est comme si le travailleur avait besoin d'obtenir des informations du gestionnaire avant de pouvoir terminer sa tâche . Pour créer la closure , vous pouvez aligner la fonction afin qu'elle voit les données dans le contexte appelant:

/* 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
}

Usage:

// 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 la closure de Douglas Crockford :

Les fonctions peuvent être définies à l'intérieur d'autres fonctions. La fonction interne a accès aux variables et aux paramètres de la fonction externe. Si une référence à une fonction interne survit (par exemple, en tant que fonction de rappel), les variables de la fonction externe survivent également.

Voir également:


En termes non-programmeur, un rappel est un fill-in-the-blank dans un programme.

Un élément commun sur plusieurs formulaires papier est «Personne à appeler en cas d'urgence». Il y a une ligne vide là. Vous écrivez le nom et le numéro de téléphone de quelqu'un. Si une urgence survient, cette personne est appelée.

  • Tout le monde obtient la même forme vierge, mais
  • Tout le monde peut écrire un numéro de contact d'urgence différent.

C'est la clé. Vous ne changez pas le formulaire (le code, généralement celui de quelqu'un d'autre). Cependant, vous pouvez remplir les informations manquantes ( votre numéro).

Exemple 1:

Les rappels sont utilisés comme méthodes personnalisées, éventuellement pour ajouter / modifier le comportement d'un programme. Par exemple, prenez du code C qui exécute une fonction, mais ne sait pas comment imprimer la sortie. Tout ce qu'il peut faire est de faire une chaîne. Quand il essaie de comprendre quoi faire avec la chaîne, il voit une ligne vide. Mais, le programmeur vous a donné le blanc pour écrire votre callback!

Dans cet exemple, vous n'utilisez pas de crayon pour remplir un set_print_callback(the_callback) vide sur une feuille de papier, vous utilisez la fonction set_print_callback(the_callback) .

  • La variable vide dans le module / code est la ligne vide,
  • set_print_callback est le crayon,
  • et the_callback est votre information que vous remplissez.

Vous avez rempli cette ligne vide dans le programme. Chaque fois qu'il a besoin d'imprimer la sortie, il regarde cette ligne vide, et suit les instructions (appelez la fonction que vous y mettez.) Pratiquement, cela permet la possibilité d'imprimer à l'écran, à un fichier journal, à une imprimante, sur une connexion réseau ou toute combinaison de ceux-ci. Vous avez rempli le vide avec ce que vous voulez faire.

Exemple 2:

Quand on vous dit que vous devez appeler un numéro d'urgence, vous allez lire ce qui est écrit sur le formulaire papier, puis appelez le numéro que vous avez lu. Si cette ligne est vide, rien ne sera fait.

La programmation Gui fonctionne de la même manière. Lorsqu'un bouton est cliqué, le programme doit déterminer ce qu'il faut faire ensuite. Il va et cherche le rappel. Ce rappel se trouve dans un espace intitulé "Voici ce que vous faites lorsque vous cliquez sur Button1"

La plupart des IDE remplissent automatiquement le vide pour vous (écrivez la méthode de base) quand vous le demandez (par exemple, button1_clicked ). Cependant ce blanc peut avoir n'importe quelle méthode que vous darn bien s'il vous plaît . Vous pouvez appeler la méthode run_computations ou butter_the_biscuits tant que vous mettez le nom de ce rappel dans le blanc approprié. Vous pouvez mettre "555-555-1212" dans le numéro d'urgence vide. Cela n'a pas beaucoup de sens, mais c'est permis.

Note finale: Cette ligne vide que vous remplissez avec le rappel? Il peut être effacé et réécrit à volonté. (Que vous le deviez ou non est une autre question, mais c'est une partie de leur pouvoir)


Il y a deux points à expliquer, l'un est comment fonctionne un rappel (en passant une fonction qui peut être appelée sans aucune connaissance de son contexte), l'autre à quoi il sert (gérer les événements de manière asynchrone).

L'analogie de l'attente d'un colis qui a été utilisé par d'autres réponses est une bonne explication. Dans un programme d'ordinateur, vous diriez à l'ordinateur d'attendre un colis. Ordinairement, il resterait là et attendrait (et ne ferait rien d'autre) jusqu'à ce que le colis arrive, peut-être indéfiniment s'il n'arrive jamais. Pour les humains, cela semble stupide, mais sans autres mesures, cela est totalement naturel à un ordinateur.

Maintenant, le rappel serait la cloche à votre porte d'entrée. Vous fournissez au service de colis un moyen de vous informer de l'arrivée du colis sans qu'ils aient à savoir où (même si) vous êtes dans la maison, ou comment fonctionne la cloche. (Par exemple, certaines "cloches" envoient un appel téléphonique.) Parce que vous avez fourni une "fonction de rappel" qui peut être "appelée" à tout moment, hors contexte, vous pouvez maintenant arrêter de vous asseoir devant le porche et événement "(d'arrivée de colis) quand il est temps.


Imaginez qu'un ami quitte votre maison et que vous lui disiez «Appelez-moi quand vous rentrerez à la maison pour que je sache que vous êtes arrivé en sécurité»; c'est (littéralement) un rappel . C'est ce qu'est une fonction de rappel, quelle que soit la langue. Vous voulez qu'une procédure vous renvoie le contrôle lorsqu'elle a terminé une tâche, vous lui donnez donc une fonction à utiliser pour vous rappeler.

En Python, par exemple,

grabDBValue( (lambda x: passValueToGUIWindow(x) ))

grabDBValue pourrait être écrit pour saisir seulement une valeur d'une base de données, puis vous laisser spécifier ce qu'il faut réellement faire avec la valeur, donc il accepte une fonction. Vous ne savez pas quand ou si grabDBValue retournera, mais si / quand c'est le cas, vous savez ce que vous voulez qu'il fasse. Ici, je passe dans une fonction anonyme (ou lambda ) qui envoie la valeur à une fenêtre GUI. Je pourrais facilement changer le comportement du programme en faisant ceci:

grabDBValue( (lambda x: passToLogger(x) ))

Les callbacks fonctionnent bien dans les langages où les fonctions sont des valeurs de première classe , tout comme les entiers habituels, les chaînes de caractères, les booléens, etc. En C, vous pouvez "passer" une fonction en lui passant un pointeur et l'appelant peut l'utiliser; en Java, l'appelant demandera une classe statique d'un certain type avec un certain nom de méthode puisqu'il n'y a pas de fonctions ("méthodes", vraiment) en dehors des classes; et dans la plupart des autres langages dynamiques, vous pouvez simplement passer une fonction avec une syntaxe simple.

Protip:

Dans les langues avec portée lexicale (comme Scheme ou Perl), vous pouvez tirer un truc comme celui-ci:

my $var = 2;
my $val = someCallerBackFunction(sub callback { return $var * 3; });
# Perlistas note: I know the sub doesn't need a name, this is for illustration

$val dans ce cas sera 6 car le callback a accès aux variables déclarées dans l'environnement lexical où il a été défini. La portée lexicale et les rappels anonymes sont une combinaison puissante justifiant une étude plus approfondie pour le programmeur débutant.


Je suis stupéfaite de voir tant de gens intelligents ne pas insister sur le fait que le mot «callback» a été utilisé de deux manières incohérentes.

Les deux moyens impliquent la personnalisation d'une fonction en passant des fonctionnalités supplémentaires (une définition de fonction, anonyme ou nommée) à une fonction existante. c'est à dire.

customizableFunc(customFunctionality)

Si la fonctionnalité personnalisée est simplement branchée dans le bloc de code, vous avez personnalisé la fonction, comme ceci.

    customizableFucn(customFunctionality) {
      var data = doSomthing();
      customFunctionality(data);
      ...
    }

Bien que ce type de fonctionnalité injectée soit souvent appelé "callback", il n'y a rien de contingent à ce sujet. Un exemple très évident est la méthode forEach dans laquelle une fonction personnalisée est fournie en tant qu'argument à appliquer à chaque élément d'un tableau pour modifier le tableau.

Mais ceci est fondamentalement distinct de l'utilisation de fonctions de "rappel" pour la programmation asynchrone , comme dans AJAX ou node.js ou simplement en assignant des fonctionnalités aux événements d'interaction de l'utilisateur (comme les clics de souris). Dans ce cas, l'idée est d'attendre qu'un événement éventuel se produise avant d'exécuter la fonctionnalité personnalisée. Ceci est évident dans le cas d'une interaction avec l'utilisateur, mais est également important dans les processus d'entrée / sortie (entrée / sortie) qui peuvent prendre du temps, comme la lecture de fichiers à partir d'un disque. C'est là que le terme "callback" prend tout son sens. Une fois qu'un processus d'E / S est démarré (comme demander à un fichier d'être lu sur le disque ou un serveur pour renvoyer des données à partir d'une requête http), un programme asynchrone n'attend pas qu'il se termine. Il peut aller de l'avant avec les tâches planifiées suivantes et répondre uniquement avec la fonctionnalité personnalisée après avoir été informé que le fichier lu ou la requête http est terminé (ou qu'il a échoué) et que les données sont disponibles pour la fonctionnalité personnalisée. C'est comme si vous appeliez une entreprise au téléphone et que vous laissiez votre numéro de «rappel» pour qu'ils puissent vous appeler lorsque quelqu'un est disponible pour vous répondre. C'est mieux que de rester en ligne pour qui sait combien de temps et ne pas être en mesure de s'occuper d'autres affaires.

L'utilisation asynchrone implique intrinsèquement certains moyens d'écoute de l'événement souhaité (par exemple, l'achèvement du processus d'entrée / sortie) de sorte que, lorsqu'elle se produit (et seulement quand elle se produit), la fonctionnalité "callback" personnalisée est exécutée. Dans l'exemple AJAX évident, lorsque les données arrivent réellement du serveur, la fonction "callback" est déclenchée pour utiliser ces données pour modifier le DOM et donc redessiner la fenêtre du navigateur dans cette mesure.

Récapituler. Certaines personnes utilisent le mot "callback" pour désigner tout type de fonctionnalité personnalisée pouvant être injectée dans une fonction existante en tant qu'argument. Mais, au moins pour moi, l'utilisation la plus appropriée du mot est où la fonction "callback" injectée est utilisée de manière asynchrone - pour être exécutée seulement lors de l'occurrence d'un événement dont elle attend d'être avertie.


Je vais essayer de garder les choses simples. Un "callback" est une fonction appelée par une autre fonction qui prend la première fonction en paramètre. La plupart du temps, un "rappel" est une fonction appelée quand quelque chose se produit. Ce quelque chose peut être appelé un "événement" dans le langage du programmeur.

Imaginez ce scénario: vous attendez un colis dans quelques jours. Le paquet est un cadeau pour votre voisin. Par conséquent, une fois que vous obtenez le paquet, vous voulez qu'il soit apporté aux voisins. Vous êtes en dehors de la ville et vous laissez des instructions pour votre conjoint.

Vous pourriez leur dire d'obtenir le paquet et l'apporter aux voisins. Si votre conjoint était aussi stupide qu'un ordinateur, ils s'asseyaient à la porte et attendaient le paquet jusqu'à ce qu'il vienne (NE FAISANT AUCUNE AUTRE) et une fois arrivé, ils l'apportaient aux voisins. Mais il y a un meilleur moyen. Dites à votre conjoint que, une fois qu'ils reçoivent le paquet, ils devraient l'apporter sur les voisins. Ensuite, ils peuvent aller sur la vie normalement jusqu'à ce qu'ils reçoivent le paquet.

Dans notre exemple, la réception du paquet est "l'événement" et l'amener aux voisins est le "rappel". Votre conjoint «exécute» vos instructions pour ramener le colis seulement lorsque le colis arrive. Beaucoup mieux!

Ce genre de pensée est évident dans la vie quotidienne, mais les ordinateurs n'ont pas le même genre de bon sens. Considérez comment les programmeurs écrivent normalement 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 que le fichier s'ouvre, avant que nous écrivions dessus. Cela "bloque" le flux d'exécution, et notre programme ne peut pas faire les autres choses qu'il pourrait avoir besoin de faire! Et si nous pouvions le faire à 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 faisons cela avec quelques langages et frameworks. C'est vraiment cool! Découvrez Node.js pour obtenir une pratique réelle avec ce genre de pensée.


Pour enseigner les rappels, vous devez d'abord apprendre le pointeur. Une fois que les élèves ont compris l'idée du pointeur vers une variable, l'idée des rappels deviendra plus facile. En supposant que vous utilisez C / C ++, ces étapes peuvent être suivies.

  • Montrez d'abord à vos élèves comment utiliser et manipuler des variables en utilisant des pointeurs en même temps que les identificateurs de variables normales.
  • Puis enseignez-leur qu'il y a des choses qui peuvent être faites seulement avec des pointeurs (comme passer une variable par référence).
  • Puis dites-leur comment le code ou les fonctions exécutables sont comme d'autres données (ou variables) dans la mémoire. Ainsi, les fonctions ont aussi des adresses ou des pointeurs.
  • Puis montrez-leur comment les fonctions peuvent être appelées avec des pointeurs de fonction et dites que ces fonctions sont appelées callbacks.
  • Maintenant, la question est, pourquoi tous ces tracas pour appeler certaines fonctions? Quel est le bénéfice? À l'instar des pointeurs de données, les rappels de fonction de pointeur ont certains avantages par rapport à l'utilisation d'identifiants normaux.
  • Le premier est que les identifiants de fonction ou les noms de fonctions ne peuvent pas être utilisés comme des données normales. Je veux dire, vous ne pouvez pas créer une structure de données avec des fonctions (comme un tableau ou une liste de fonctions liées). Mais avec les callbacks, vous pouvez faire un tableau, une liste chaînée ou les utiliser avec d'autres données comme dans le dictionnaire des paires clé-valeur ou des arbres, ou tout autre chose. C'est un avantage puissant. Et d'autres avantages sont en fait l'enfant de celui-ci.
  • L'utilisation la plus courante des rappels est visible dans la programmation du pilote d'événement. Où une ou plusieurs fonctions sont exécutées en fonction d'un signal entrant. Avec les rappels, un dictionnaire peut être maintenu pour mapper des signaux avec des rappels. Ensuite, la résolution du signal d'entrée et l'exécution du code correspondant deviennent beaucoup plus faciles.
  • La deuxième utilisation des rappels qui me viennent à l'esprit est les fonctions d'ordre supérieur. Les fonctions qui prennent d'autres fonctions comme arguments d'entrée. Et pour envoyer des fonctions en tant qu'arguments, nous avons besoin de callbacks. Un exemple peut être une fonction qui prend un tableau et un rappel. Ensuite, il effectue le rappel sur chacun des éléments du tableau et renvoie les résultats dans un autre tableau. Si nous passons à la fonction un rappel de doublage, nous obtenons un tableau de valeurs doublées. Si nous passons un rappel au carré, nous obtenons des carrés. Pour les racines carrées, envoyez simplement un rappel approprié. This cannot be done with normal functions.

There might many more things. Involve the students and they will discover. J'espère que cela t'aides.


Sans callback ni d'autres ressources de programmation spéciales (comme threading, et autres), un programme est exactement une séquence d'instructions qui sont exécutées séquentiellement les unes après les autres , et même avec une sorte de "comportement dynamique" déterminé par certaines conditions, tous les scénarios possibles doit être préalablement programmé .

Donc, si nous devons fournir un comportement dynamique réel à un programme, nous pouvons utiliser le rappel. Avec callback vous pouvez indiquer par des paramètres, un programme pour appeler un autre programme fournissant des paramètres définis précédemment et peut espérer des résultats ( c'est la signature du contrat ou de l'opération ), donc ces résultats peuvent être produits / traités par un programme tiers. 't déjà connu.

Cette technique est le fondement du polymorphisme appliqué aux programmes, fonctions, objets et toutes les autres unités de code exécutées par des ordinateurs.

Le monde humain utilisé comme exemple de rappel est bien expliqué quand vous faites un travail, supposons que vous êtes un peintre ( ici vous êtes le programme principal, qui peint ) et appelez parfois votre client pour lui demander d'approuver le résultat de votre travail , donc, il décide si la photo est bonne ( votre client est le programme tiers ).

Dans l'exemple ci-dessus vous êtes un peintre et "déléguez" à d'autres le travail pour approuver le résultat, l'image est le paramètre, et chaque nouveau client (la "fonction" rappelée) change le résultat de votre travail en décidant ce qu'il veut à propos de l'image ( la décision prise par les clients est le résultat renvoyé par la "fonction de rappel" ).

J'espère que cette explication peut être utile.


Supposons que vous deviez me confier une tâche potentiellement longue: obtenir les noms des cinq premières personnes uniques que vous rencontrez. Cela peut prendre des jours si je suis dans une zone peu peuplée. Vous n'êtes pas vraiment intéressé à vous asseoir sur vos mains pendant que je cours, alors vous dites: "Quand vous avez la liste, appelez-moi sur ma cellule et lisez-le moi." Voici le numéro. ".

Vous m'avez donné une référence de rappel - une fonction que je suis censé exécuter pour pouvoir continuer le traitement.

En JavaScript, il pourrait ressembler à ceci:

var lottoNumbers = [];
var callback = function(theNames) {
  for (var i=0; i<theNames.length; i++) {
    lottoNumbers.push(theNames[i].length);
  }
};

db.executeQuery("SELECT name " +
                "FROM tblEveryOneInTheWholeWorld " +
                "ORDER BY proximity DESC " +
                "LIMIT 5", callback);

while (lottoNumbers.length < 5) {
  playGolf();
}
playLotto(lottoNumbers);

Cela pourrait probablement être amélioré de plusieurs façons. Par exemple, vous pouvez fournir un second rappel: si cela prend plus d'une heure, appelez le téléphone rouge et dites à la personne que les réponses ont expiré.


Toujours mieux de commencer par un exemple :).

Supposons que vous avez deux modules A et B.

Vous voulez que le module A soit averti lorsqu'un événement / une condition survient dans le module B. Cependant, le module B n'a aucune idée de votre module A. Tout ce qu'il sait, c'est une adresse à une fonction particulière (du module A) via un pointeur de fonction fourni par le module A.

Tout ce que B doit faire maintenant, c'est "callback" dans le module A quand un événement / une condition particulière se produit en utilisant le pointeur de fonction. A peut faire un traitement ultérieur à l'intérieur de la fonction de rappel.

*) Un avantage évident ici est que vous êtes en train de faire abstraction de tout ce qui concerne le module A à partir du module B. Le module B n'a pas à se soucier de qui / quel module A est.


Une explication métaphorique:

J'ai un colis que je veux remettre à un ami, et je veux aussi savoir quand mon ami le reçoit.

Alors je prends le colis à la poste et je leur demande de le livrer. Si je veux savoir quand mon ami reçoit le colis, j'ai deux options:

(a) Je peux attendre au bureau de poste jusqu'à ce qu'il soit livré.

(b) Je recevrai un courriel quand il sera livré.

L'option (b) est analogue à un rappel.


Vous avez du code que vous voulez exécuter. Normalement, lorsque vous l'appelez, vous attendez qu'il soit terminé avant de continuer (ce qui peut rendre votre application grise / produire un temps de rotation pour un curseur).

Une méthode alternative consiste à exécuter ce code en parallèle et à poursuivre votre propre travail. Mais que faire si votre code original doit faire des choses différentes en fonction de la réponse du code qu'il a appelé? Eh bien, dans ce cas, vous pouvez passer le nom / l'emplacement du code que vous voulez qu'il appelle quand il est fait. C'est un "rappel".

Code normal: Demande d'information-> Information sur le processus-> Traiter avec les résultats du traitement-> Continuer à faire d'autres choses.

Avec les rappels: Demande d'informations-> Informations sur le processus-> Continuer à faire d'autres choses. Et à un moment plus tard-> Traiter avec les résultats de traitement.


“In computer programming, a callback is a reference to executable code, or a piece of executable code, that is passed as an argument to other code. This allows a lower-level software layer to call a subroutine (or function) defined in a higher-level layer.” - Wikipedia

Callback in C using Function Pointer

In C, callback is implemented using Function Pointer. Function Pointer - as the name suggests, is a pointer to a function.

For example, int (*ptrFunc) ();

Here, ptrFunc is a pointer to a function that takes no arguments and returns an integer. DO NOT forget to put in the parenthesis, otherwise the compiler will assume that ptrFunc is a normal function name, which takes nothing and returns a pointer to an integer.

Here is some code to demonstrate the function pointer.

#include<stdio.h>
int func(int, int);
int main(void)
{
    int result1,result2;
    /* declaring a pointer to a function which takes
       two int arguments and returns an integer as result */
    int (*ptrFunc)(int,int);

    /* assigning ptrFunc to func's address */                    
    ptrFunc=func;

    /* calling func() through explicit dereference */
    result1 = (*ptrFunc)(10,20);

    /* calling func() through implicit dereference */        
    result2 = ptrFunc(10,20);            
    printf("result1 = %d result2 = %d\n",result1,result2);
    return 0;
}

int func(int x, int y)
{
    return x+y;
}

Now let us try to understand the concept of Callback in C using function pointer.

The complete program has three files: callback.c, reg_callback.h and reg_callback.c.

/* callback.c */
#include<stdio.h>
#include"reg_callback.h"

/* callback function definition goes here */
void my_callback(void)
{
    printf("inside my_callback\n");
}

int main(void)
{
    /* initialize function pointer to
    my_callback */
    callback ptr_my_callback=my_callback;                        
    printf("This is a program demonstrating function callback\n");
    /* register our callback function */
    register_callback(ptr_my_callback);                          
    printf("back inside main program\n");
    return 0;
}

/* reg_callback.h */
typedef void (*callback)(void);
void register_callback(callback ptr_reg_callback);


/* reg_callback.c */
#include<stdio.h>
#include"reg_callback.h"

/* registration goes here */
void register_callback(callback ptr_reg_callback)
{
    printf("inside register_callback\n");
    /* calling our callback function my_callback */
    (*ptr_reg_callback)();                               
}

If we run this program, the output will be

This is a program demonstrating function callback inside register_callback inside my_callback back inside main program

The higher layer function calls a lower layer function as a normal call and the callback mechanism allows the lower layer function to call the higher layer function through a pointer to a callback function.

Callback in Java Using Interface

Java does not have the concept of function pointer It implements Callback mechanism through its Interface mechanism Here instead of a function pointer, we declare an Interface having a method which will be called when the callee finishes its task

Let me demonstrate it through an example:

The Callback Interface

public interface Callback
{
    public void notify(Result result);
}

The Caller or the Higher Level Class

public Class Caller implements Callback
{
Callee ce = new Callee(this); //pass self to the callee

//Other functionality
//Call the Asynctask
ce.doAsynctask();

public void notify(Result result){
//Got the result after the callee has finished the task
//Can do whatever i want with the result
}
}

The Callee or the lower layer function

public Class Callee {
Callback cb;
Callee(Callback cb){
this.cb = cb;
}

doAsynctask(){
//do the long running task
//get the result
cb.notify(result);//after the task is completed, notify the caller
}
}

Callback Using EventListener pattern

  • Élément de liste

This pattern is used to notify 0 to n numbers of Observers/Listeners that a particular task has finished

  • Élément de liste

The difference between Callback mechanism and EventListener/Observer mechanism is that in callback, the callee notifies the single caller, whereas in Eventlisener/Observer, the callee can notify anyone who is interested in that event (the notification may go to some other parts of the application which has not triggered the task)

Let me explain it through an example.

The Event Interface

public interface Events {

public void clickEvent();
public void longClickEvent();
}

Class Widget

package com.som_itsolutions.training.java.exampleeventlistener;

import java.util.ArrayList;
import java.util.Iterator;

public class Widget implements Events{

    ArrayList<OnClickEventListener> mClickEventListener = new ArrayList<OnClickEventListener>(); 
    ArrayList<OnLongClickEventListener> mLongClickEventListener = new ArrayList<OnLongClickEventListener>();

    @Override
    public void clickEvent() {
        // TODO Auto-generated method stub
        Iterator<OnClickEventListener> it = mClickEventListener.iterator();
                while(it.hasNext()){
                    OnClickEventListener li = it.next();
                    li.onClick(this);
                }   
    }
    @Override
    public void longClickEvent() {
        // TODO Auto-generated method stub
        Iterator<OnLongClickEventListener> it = mLongClickEventListener.iterator();
        while(it.hasNext()){
            OnLongClickEventListener li = it.next();
            li.onLongClick(this);
        }

    }

    public interface OnClickEventListener
    {
        public void onClick (Widget source);
    }

    public interface OnLongClickEventListener
    {
        public void onLongClick (Widget source);
    }

    public void setOnClickEventListner(OnClickEventListener li){
        mClickEventListener.add(li);
    }
    public void setOnLongClickEventListner(OnLongClickEventListener li){
        mLongClickEventListener.add(li);
    }
}

Class Button

public class Button extends Widget{
private String mButtonText;
public Button (){
} 
public String getButtonText() {
return mButtonText;
}
public void setButtonText(String buttonText) {
this.mButtonText = buttonText;
}
}

Class Checkbox

public class CheckBox extends Widget{
private boolean checked;
public CheckBox() {
checked = false;
}
public boolean isChecked(){
return (checked == true);
}
public void setCheck(boolean checked){
this.checked = checked;
}
}

Activity Class

package com.som_itsolutions.training.java.exampleeventlistener;

public class Activity implements Widget.OnClickEventListener
{
    public Button mButton;
    public CheckBox mCheckBox;
    private static Activity mActivityHandler;
    public static Activity getActivityHandle(){
        return mActivityHandler;
    }
    public Activity ()
    {
        mActivityHandler = this;
        mButton = new Button();
        mButton.setOnClickEventListner(this);
        mCheckBox = new CheckBox();
        mCheckBox.setOnClickEventListner(this);
        } 
    public void onClick (Widget source)
    {
        if(source == mButton){
            mButton.setButtonText("Thank you for clicking me...");
            System.out.println(((Button) mButton).getButtonText());
        }
        if(source == mCheckBox){
            if(mCheckBox.isChecked()==false){
                mCheckBox.setCheck(true);
                System.out.println("The checkbox is checked...");
            }
            else{
                mCheckBox.setCheck(false);
                System.out.println("The checkbox is not checked...");
            }       
        }
    }
    public void doSomeWork(Widget source){
        source.clickEvent();
    }   
}

Other Class

public class OtherClass implements Widget.OnClickEventListener{
Button mButton;
public OtherClass(){
mButton = Activity.getActivityHandle().mButton;
mButton.setOnClickEventListner(this);//interested in the click event                        //of the button
}
@Override
public void onClick(Widget source) {
if(source == mButton){
System.out.println("Other Class has also received the event notification...");
}
}

Main Class

public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Activity a = new Activity();
OtherClass o = new OtherClass();
a.doSomeWork(a.mButton);
a.doSomeWork(a.mCheckBox);
}
}

As you can see from the above code, that we have an interface called events which basically lists all the events that may happen for our application. The Widget class is the base class for all the UI components like Button, Checkbox. These UI components are the objects that actually receive the events from the framework code. Widget class implements the Events interface and also it has two nested interfaces namely OnClickEventListener & OnLongClickEventListener

These two interfaces are responsible for listening to events that may occur on the Widget derived UI components like Button or Checkbox. So if we compare this example with the earlier Callback example using Java Interface, these two interfaces work as the Callback interface. So the higher level code (Here Activity) implements these two interfaces. And whenever an event occurs to a widget, the higher level code (or the method of these interfaces implemented in the higher level code, which is here Activity) will be called.

Now let me discuss the basic difference between Callback and Eventlistener pattern. As we have mentioned that using Callback, the Callee can notify only a single Caller. But in the case of EventListener pattern, any other part or class of the Application can register for the events that may occur on the Button or Checkbox. The example of this kind of class is the OtherClass. If you see the code of the OtherClass, you will find that it has registered itself as a listener to the ClickEvent that may occur in the Button defined in the Activity. Interesting part is that, besides the Activity ( the Caller), this OtherClass will also be notified whenever the click event occurs on the Button.


Les rappels sont plus facilement décrits en termes de système téléphonique. Un appel de fonction est analogue à appeler quelqu'un au téléphone, lui poser une question, obtenir une réponse et raccrocher; l'ajout d'un rappel change l'analogie de sorte que, après lui avoir posé une question, vous lui donniez aussi votre nom et votre numéro pour qu'elle vous rappelle avec la réponse. - Paul Jakubik, "Implémentations de rappel en C ++"


A callback is a method that is scheduled to be executed when a condition is met.

An "real world" example is a local video game store. You are waiting for Half-Life 3. Instead of going to the store every day to see if it is in, you register your email on a list to be notified when the game is available. The email becomes your "callback" and the condition to be met is the game's availability.

A "programmers" example is a web page where you want to perform an action when a button is clicked. You register a callback method for a button and continue doing other tasks. When/if the user cicks on the button, the browser will look at the list of callbacks for that event and call your method.

A callback is a way to handle events asynchronously. You can never know when the callback will be executed, or if it will be executed at all. The advantage is that it frees your program and CPU cycles to perform other tasks while waiting for the reply.


A callback is a self-addressed stamped envelope. When you call a function, that is like sending a letter. If you want that function to call another function you provide that information in the form of a reference or address.


I think it's an rather easy task to explain.

At first callback are just ordinary functions.
And the further is, that we call this function (let's call it A) from inside another function (let's call it B).

The magic about this is that I decide, which function should be called by the function from outside B.

At the time I write the function BI don't know which callback function should be called. At the time I call function BI also tell this function to call function A. That is all.


In plain english a callback is a promise. Joe, Jane, David and Samantha share a carpool to work. Joe is driving today. Jane, David and Samantha have a couple of options:

  1. Check the window every 5 minutes to see if Joe is out
  2. Keep doing their thing until Joe rings the door bell.

Option 1: This is more like a polling example where Jane would be stuck in a "loop" checking if Joe is outside. Jane can't do anything else in the mean time.

Option 2: This is the callback example. Jane tells Joe to ring her doorbell when he's outside. She gives him a "function" to ring the door bell. Joe does not need to know how the door bell works or where it is, he just needs to call that function ie ring the door bell when he's there.

Callbacks are driven by "events". In this example the "event" is Joe's arrival. In Ajax for example events can be "success" or "failure" of the asynchronous request and each can have the same or different callbacks.

In terms of JavaScript applications and callbacks. We also need to understand "closures" and application context. What "this" refers to can easily confuse JavaScript developers. In this example within each person's "ring_the_door_bell()" method/callback there might be some other methods that each person need to do based on their morning routine ex. "turn_off_the_tv()". We would want "this" to refer to the "Jane" object or the "David" object so that each can setup whatever else they need done before Joe picks them up. This is where setting up the callback with Joe requires parodying the method so that "this" refers to the right object.

J'espère que cela pourra aider!


Think of a method as giving a task to a coworker. A simple task might be the following:

Solve these equations:
x + 2 = y
2 * x = 3 * y

Your coworker diligently does the math and gives you the following result:

x = -6
y = -4

But your coworker has a problem, he doesn't always understand notations, such as ^ , but he does understand them by their description. Such as exponent . Everytime he finds one of these you get back the following:

I don't understand "^"

This requires you to rewrite your entire instruction set again after explaining what the character means to your coworker, and he doesn't always remember in between questions. And he has difficulty remembering your tips as well, such as just ask me. He always follows your written directions as best he can however.

You think of a solution, you just add the following to all of your instructions:

If you have any questions about symbols, call me at extension 1234 and I will tell you its name.

Now whenever he has a problem he calls you and asks, rather than giving you a bad response and making the process restart.


This of it in terms of downloading a webpage:

Your program runs on a cellphone and is requesting the webpage http://www.google.com . If you write your program synchronously, the function you write to download the data will be running continuously until all the data is download. This means your UI will not refresh and will basically appear frozen. If you write your program using callbacks, you request the data and say "execute this function when you've finished." This allows the UI to still allow user interaction while the file is downloading. Once the webpage has finished downloading, your result function (callback) is called and you can handle the data.

Fondamentalement, cela vous permet de demander quelque chose et de continuer à l'exécuter en attendant le résultat. Une fois que le résultat vous revient via une fonction de rappel, vous pouvez reprendre l'opération là où elle s'était arrêtée.







callback