Node JS fonctions anonymes et rappels

Quelqu'un aide-moi. J'ai lu beaucoup de documentation javascript et je joue avec javascript.

Je suis en mesure d'utiliser les fonctions, mais je ne comprends pas tout à fait ce jazz syntaxique essentiel ici

var http = require('http'); http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n'); }).listen(1337, 'myhost'); console.log('Server running at http://myhost:1337/'); 

Je ne peux pas comprendre pourquoi il est correct d'utiliser req et res dans la fonction anonyme ci-dessus. C'est comme si ils vivaient quelque part dans l'http. Ils ne sont déclarés nulle part! Ils sont constitués de noms de variables dans une fonction anonyme qui fait référence à des objets internes ou quelque chose. C'est fou.

Comment un rappel fonctionne comme ça?

Ou comme

  stream.on('data', function(data){ // use data... i dont know where its coming from // or how it got there, but use it }); 

Si vous pouvez publier un petit exemple qui imite ce processus et cette syntaxe ou explique comment ces fonctions de rappel peuvent fonctionner comme ceci ou comment je peux transmettre ces variables non déclarées dans des fonctions comme celle-ci, je l'apprécierais grandement.

Un exemple similaire à celui de la réponse ci-dessous.

  var b = { somefunction : function( data ){ var x = 100; x = x+1; // 101 return data(x); // returns the callback function data w/ value x } }; b.somefunction(function(foo){ foo++; // 101 + 1 console.log(foo); // prints 102 }); 

Le problème principal est que Javascript est un langage fonctionnel afin que vous puissiez passer les fonctions en tant que paramètres à d'autres fonctions. Dans d'autres langues, vous avez peut-être vécu en passant un pointeur ou un handle à une fonction, par exemple. Considérons des cas simples dans lesquels vous avez des fonctions mathématiques:

 function add(a,b) {return (a+b)}; function subtract(a,b) {return (ab)}: 

Maintenant, je pourrais créer une nouvelle fonction:

 function longWayAroundTheBarn(num1,num2,theFunc) { // invoke the passed function with the passed parameters return theFunc(num1,num2); } 

Et appelez-le comme ceci:

 console.log(longWayAroundTheBarn(1,2),add); > 3 

Ou même comme ceci:

 console.log(longWayAroundTheBarn(longWayAroundTheBarn(2,2,subtract),4,add); > 4 

Évidemment, ce serait un rappel d'utilisation stupide, mais vous pouvez imaginer généralement que la capacité de "plug-in" d'une fonction de cette façon peut être assez puissante.

Considérez si vous ne pouviez pas passer des fonctions. Cela pourrait être une façon de mettre en œuvre ceci:

 function reallyLongWayAround(num1,num2,funcName) { if(funcName==='add') return add(num1 ,num2); else if (funcName === 'subtract') return subtract(num1, num2); } 

Vous pouvez imaginer qu'en plus d'être un code vraiment fastidieux à avoir à écrire et à entretenir, ce n'est pas si puissant que la fonction reallyLongWayAround ne peut jamais appeler un code qu'il connaissait. En passant des fonctions, mon longWayAroundTheBarn ne se soucie pas si je crée de nouvelles fonctions et je la passe. Notez que, en raison d'un typage faible, il n'a même pas besoin de se soucier des paramètres passés. Peut-être que vous voulez implémenter quelque chose comme

  function businessDaysBetween(d1,d2) { // implementation left as a reader exercise }; 

Cela fonctionnerait très bien pour appeler:

 longWayAroundTheBarn(new Date(2014,1,15), new Date(2014,1,22),businessDaysBetween) 

Si vous req cas spécifique que vous avez soulevé, req et res ne sont pas des «variables locales» comme l'indique une réponse: elles sont appelées des paramètres ou des arguments. Vous ne leur transmetz rien. Ils sont transmis par la fonction d'appel. Vous pourriez les appeler fred et barney si vous le vouliez, bien que ce serait une idée terrible. Le point principal est qu'ils seront appelés remplis avec des objets de demande et de réponse.

Vous n'avez même pas à avoir les paramètres dans la signature de votre fonction, vous pourriez simplement avoir un rappel comme ci-dessous, et utiliser le deuxième paramètre passé à votre fonction en lisant le tableau des arguments (notez, ce n'est pas en fait un tableau, mais Se comporte de la même manière à bien des égards). Ce serait une idée terrible, terrible, mais encore une fois, en essayant d'illustrer ce point.

  var http = require('http'); http.createServer(function () { arguments[1].writeHead(200, {'Content-Type': 'text/plain'}); arguments[1].end('Hello World\n'); }).listen(1337, 'myhost'); 

Les req et res sont en fait des variables locales de la fonction anonyme.
J'ai un exemple ci-dessous similaire aux codes affichés dans votre question.

 // static class var HelperClass = { "doSomething" : function ( callback ) { // do something here, for example ajax call to a server var data = ajaxCallFromServer(); // return the data via callback callback ( data ); }; }; // you codes here calling the HelperClass // calling .doSomething method with an anonymous function callback // that expects 1 parameter. This parameter is returned by the above // code via callback ( data ). And in the anonymous function // i called it as retData, you can call it whatever you like HelperClass.doSomething( function ( retData ) { // do soemthing with your retData here }); 

Le point est que la fonction http.createServer prend un argument qui n'est pas une variable, mais une fonction, si cela a du sens. En javascript, vous pouvez le faire. Et cette fonction s'attend à des arguments qui sont spécifiés dans son API. Vous pouvez le rendre anonyme, comme dans votre exemple, ou déclaré comme ci-dessous:

 function serverFunction(req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n'); } var http = require('http'); http.createServer(serverFunction).listen(1337, 'myhost'); 

Mais en fin de compte, cela ne compte pas, il se comporte juste en fonction de ce qui est spécifié dans son API.

Vous devriez utiliser la documentation. Ainsi, par exemple pour createServer, suivez cette page – http://nodejs.org/api/http.html#http_http_createserver_requestlistener

Http.createServer ([requestListener]) # Renvoie un nouvel objet de serveur Web.

Le requestListener est une fonction qui est automatiquement ajoutée à l'événement 'request' .

Ensuite, vous vérifiez l'événement «demande» –

Événement: 'demande' # fonction (demande, réponse) {}

Émis chaque fois qu'il y a une demande. Notez qu'il peut y avoir plusieurs requêtes par connexion (dans le cas de connexions keep-alive). Demande est une instance de http.IncomingMessage et la réponse est une instance de http.ServerResponse.

En ce qui concerne le flux, exactement le même. Les documents ici – http://nodejs.org/api/stream.html#stream_writable_stream

Chercher

Événement: 'données'