Comprendre le code asynchrone dans les termes de Layman

Je comprends l'essentiel de l'asynchrone: les choses ne s'exécutent pas séquentiellement. Et je comprends qu'il y ait quelque chose de très puissant à ce sujet … prétendument. Mais pour la vie de moi, je ne peux pas m'enrouler dans le code. Jetons un coup d'oeil sur le code asynchrone Node.JS que j'ai écrite … mais je ne comprends pas vraiment.

function newuser(response, postData) { console.log("Request handler 'newuser' was called."); var body = '<html>' + '<head>' + '<meta http-equiv="Content-Type" content="text/html; ' + 'charset=UTF-8" />' + '</head>' + '<body>' + '<form action=" /thanks" method="post">' + '<h1> First Name </h1>' + '<textarea name="text" rows="1" cols="20"></textarea>' + '<h1> Last Name </h1>' + '<textarea name="text" rows="1" cols="20"></textarea>' + '<h1> Email </h1>' + '<textarea name="text" rows="1" cols="20"></textarea>' + '<input type="submit" value="Submit text" />' + '</body>' + '</html>'; response.writeHead(200, { "Content-Type": "text/html" }); response.write(body); response.end(); } 

D'où est venu la réponse? PostData? Pourquoi ne puis-je pas définir une variable dans ce "rappel", puis l'utiliser en dehors du rappel? Existe-t-il un moyen d'avoir quelques éléments séquentiels alors que le reste du programme est asynchrone?

Je ne sais pas où cette fonction est utilisée, mais le point de rappel est que vous les transmettez à une fonction qui fonctionne de manière asynchrone; Il stocke votre rappel et, lorsque cette fonction est effectuée avec tout ce qu'il doit faire, il appellera votre rappel avec les paramètres nécessaires. Un exemple d'avant en arrière est probablement le meilleur.

Imaginez que nous avons un cadre, et il y a une opération qui fonctionne longtemps, récupérer des données de la base de données.

 function getStuffFromDatabase() { // this takes a long time }; 

Comme nous ne voulons pas qu'il fonctionne de façon synchrone, nous permettrons à l'utilisateur de passer un rappel.

 function getStuffFromDatabase(callback) { // this takes a long time }; 

Nous allons simuler la prise de temps prolongé avec un appel pour setTimeout ; Nous allons également prétendre que nous avons obtenu des données de la base de données, mais nous allons simplement coder une valeur de chaîne.

 function getStuffFromDatabase(callback) { setTimeout(function() { var results = "database data"; }, 5000); }; 

Enfin, une fois que nous avons les données, nous appelons le rappel fourni par l'utilisateur de la fonction du cadre.

 function getStuffFromDatabase(callback) { setTimeout(function() { var results = "database data"; callback(results); }, 5000); }; 

En tant qu'utilisateur du cadre, vous feriez quelque chose comme ceci pour utiliser la fonction:

 getStuffFromDatabase(function(data) { console.log("The database data is " + data); }); 

Ainsi, comme vous pouvez voir les data (même que la response et postData dans votre exemple) proviennent de la fonction dans laquelle vous passez votre rappel; Il vous donne ces données quand il sait ce que ces données devraient être.

La raison pour laquelle vous ne pouvez pas définir une valeur dans votre rappel et l'utiliser en dehors du rappel est parce que le rappel lui-même ne se produit pas plus tard dans le temps.

 // executed immediately executed sometime in the future // | | by getStuffFromDatabase // vv getStuffFromDatabase(function(data) { var results = data; // <- this isn't available until sometime in the future! }); console.log(results); // <- executed immediately 

Lorsque la console.log fonctionne, l'affectation des var results n'est pas encore arrivé!

Vous avez ici plusieurs questions non liées:

1) Le pouvoir d'async est de pouvoir faire plusieurs choses en même temps sans verrouiller le thread principal. En nœud et js en général, cela s'applique en particulier aux demandes de fichiers ajax. Cela signifie que je peux déclencher plusieurs appels asynchrones pour récupérer les fichiers et ne pas verrouiller le thread principal pendant qu'il rend le contenu. Mon framework préféré est jQuery, qui a convenablement $ .Deferred qui enveloppe et standardise les appels asynchrones pour l'utilisation de jQuery.

2) la réponse et postData proviennent de la méthode parent. Il n'y a rien de magique ici, c'est un appel de fonction normale, donc les valeurs sont créées ailleurs et passées dans cette invocation. Selon la structure de nœud que vous avez, la signature exacte de votre méthode va changer.

3) Vous pouvez définir une variable globale dans votre rappel si elle est correctement dimensionnée. Il semble toutefois que vous ayez besoin d'aide pour apprendre quelle est la portée. Voici quelques liens

http://www.digital-web.com/articles/scope_in_javascript/

http://robertnyman.com/2008/10/09/explaining-javascript-scope-and-closures/

4) Une fois que vous devenez asynchrone, vous ne pouvez jamais revenir en arrière, en tirant parti des objets promis et différés, comme avec jQuery Deferreds, vous pouvez attendre plusieurs asynchras pour terminer avant de continuer votre exécution dans un autre asynch. Les différés sont vos amis.

http://api.jquery.com/category/deferred-object/

On dirait que vous travaillez dans le Node Beginner Book . Je vous encourage à travailler sur l'ensemble du livre, c'est vraiment une excellente introduction. Si vous essayez de mieux comprendre Javascript, les vidéos de Douglas Crockford sur YouTube sont un excellent aperçu: 1 , 2 .

Le code que vous avez affiché n'a pas assez de contexte pour que je vous aide vraiment. response est un paramètre que vous transmettez à votre fonction, il ne provient pas de PostData. Si vous travaillez avec le code de la manière suggérée par le Node Beginner Book, vous êtes probablement en train de répondre à votre nouvelle fonction utilisateur complètement de la fonction createServer, qui fait partie du module http fourni avec Node.

Vous ne pouvez pas définir une variable dans le rappel, puis l'utiliser dans le rappel car Javascript est légalement étendu. Voici un message de débordement de pile sur le sujet de la portée de Javascript. La première vidéo de Doug Crockford que j'ai publiée a également une excellente explication des règles de définition de Javascript.

Javascript n'est pas nécessairement asynchrone. Il fournit simplement des fonctions anonymes qui sont des fermetures, qui sont un outil utile pour la mise en œuvre facile de la logique asynchrone. Encore une fois, le Node Beginner Book montre un bon exemple d'écriture de code synchrone avec Node (pas ce que vous voulez), puis réécrivez-le pour le rendre asynchrone.