Une fonction de rappel est simplement une fonction que vous passez à une autre fonction afin que la fonction puisse l'appeler ultérieurement. Ceci est couramment observé dans les API asynchrones ; l'appel d'API retourne immédiatement car il est asynchrone, vous lui passez donc une fonction que l'API peut appeler lorsqu'elle a terminé d'exécuter sa tâche asynchrone.
L'exemple le plus simple auquel je puisse penser en JavaScript est la setTimeout()
fonction. C'est une fonction globale qui accepte deux arguments. Le premier argument est la fonction de rappel et le deuxième argument est un délai en millisecondes. La fonction est conçue pour attendre la durée appropriée, puis appeler votre fonction de rappel.
setTimeout(function () {
console.log("10 seconds later...");
}, 10000);
Vous avez peut-être déjà vu le code ci-dessus, mais vous n'avez tout simplement pas réalisé que la fonction que vous transmettiez s'appelait une fonction de rappel. Nous pourrions réécrire le code ci-dessus pour le rendre plus évident.
var callback = function () {
console.log("10 seconds later...");
};
setTimeout(callback, 10000);
Les rappels sont utilisés partout dans Node car Node est construit à partir de zéro pour être asynchrone dans tout ce qu'il fait. Même lorsque vous parlez au système de fichiers. C'est pourquoi une tonne d'API Node internes acceptent les fonctions de rappel comme arguments plutôt que de renvoyer des données que vous pouvez attribuer à une variable. Au lieu de cela, il invoquera votre fonction de rappel, en passant les données souhaitées en argument. Par exemple, vous pouvez utiliser la fs
bibliothèque de Node pour lire un fichier. Le fs
module expose deux fonctions API uniques: readFile
et readFileSync
.
La readFile
fonction est asynchrone alors que ce readFileSync
n'est évidemment pas le cas. Vous pouvez voir qu'ils ont l'intention que vous utilisiez les appels asynchrones chaque fois que possible car ils les ont appelés readFile
et readFileSync
au lieu de readFile
et readFileAsync
. Voici un exemple d'utilisation des deux fonctions.
Synchrone:
var data = fs.readFileSync('test.txt');
console.log(data);
Le code ci-dessus bloque l'exécution du thread jusqu'à ce que tout le contenu de test.txt
soit lu en mémoire et stocké dans la variable data
. Dans le nœud, cela est généralement considéré comme une mauvaise pratique. Cependant, il y a des moments où c'est utile, par exemple lors de l'écriture d'un petit script rapide pour faire quelque chose de simple mais ennuyeux et vous ne vous souciez pas beaucoup de gagner chaque nanoseconde de temps que vous pouvez.
Asynchrone (avec rappel):
var callback = function (err, data) {
if (err) return console.error(err);
console.log(data);
};
fs.readFile('test.txt', callback);
Tout d'abord, nous créons une fonction de rappel qui accepte deux arguments err
et data
. Un problème avec les fonctions asynchrones est qu'il devient plus difficile de piéger les erreurs, de sorte que de nombreuses API de style rappel transmettent des erreurs comme premier argument à la fonction de rappel. Il est recommandé de vérifier si err
a une valeur avant de faire autre chose. Si tel est le cas, arrêtez l'exécution du rappel et consignez l'erreur.
Les appels synchrones ont un avantage lorsqu'il y a des exceptions levées car vous pouvez simplement les attraper avec un try/catch
bloc.
try {
var data = fs.readFileSync('test.txt');
console.log(data);
} catch (err) {
console.error(err);
}
Dans les fonctions asynchrones, cela ne fonctionne pas de cette façon. L'appel API revient immédiatement donc il n'y a rien à attraper avec le try/catch
. Les API asynchrones appropriées qui utilisent des rappels captureront toujours leurs propres erreurs, puis les transmettront au rappel où vous pourrez les gérer comme bon vous semble.
En plus des rappels, il existe un autre style d'API populaire couramment utilisé, appelé la promesse. Si vous souhaitez en savoir plus sur eux, vous pouvez lire l'intégralité du blog que j'ai écrit sur la base de cette réponse ici .