Des Appels asynchrones et la Récursivité avec Node.js
Je suis à la recherche d'exécuter un rappel lors de l'achèvement complet d'une fonction récursive qui peut aller pour une période indéterminée. Je suis aux prises avec async questions et en espérant obtenir de l'aide. Le code, à l'aide de la request
module, est comme suit:
var start = function(callback) {
request.get({
url: 'aaa.com'
}, function (error, response, body) {
var startingPlace = JSON.parse(body).id;
recurse(startingPlace, callback);
});
};
var recurse = function(startingPlace, callback) {
request.get({
url: 'bbb'
}, function(error, response, body) {
//store body somewhere outside these funtions
//make second request
request.get({
url: 'ccc'
}, function(error, response, body) {
var anArray = JSON.parse(body).stuff;
if (anArray) {
anArray.forEach(function(thing) {
request.get({
url: 'ddd'
}, function(error, response, body) {
var nextPlace = JSON.parse(body).place;
recurse(nextPlace);
});
})
}
});
});
callback();
};
start(function() {
//calls final function to print out results from storage that gets updated each recursive call
finalFunction();
});
Il semble qu'une fois mon code va passé le for
boucle dans le imbriqués les demandes, il continue de la demande et la fin de la fonction initiale appel alors que les appels récursifs sont toujours en cours. Je le veux de ne pas finir le plus haut niveau de l'itération jusqu'à ce que tous les imbriquée appels récursifs ont terminé (que je n'ai aucun moyen de savoir combien il y en a).
Toute aide est GRANDEMENT appréciée!
Vous avez besoin de réparer beaucoup de choses. (1) le Changement
recurse(nextPlace);
à recurse(nextPlace, callback);
(2) Si elle n'est pas un tableau dans votre test, la récursivité s'arrête, donc, juste après la if(anArray) {....}
écrire callback();
(3) Supprimer entièrement le callback();
que vous avez tout en bas (4) Dans les commentaires de la partie si vous laissez quelque chose asynchrone arriver ou si l'exécution s'arrête, vous devriez passer de façon appropriée ou appelez le (à l'aide de return callback();
cette fois), la fonction de rappel respectivement. Vous êtes ensemble. En tout cas, ne (1) - (3) et vous permettra de savoir ce qui se passe.J'ai seulement besoin de la dernière fonction qui doit être appelée une fois TOUS les récursivité boucles sont complètes. Cela permettra de l'appeler après chaque boucle a été achevé. Ma deuxième préoccupation, et la plus grande préoccupation est de savoir comment faire des requêtes HTTP de blocage - maintenant, une fois qu'ils sont appelés, la boucle continue et de ne pas attendre pour eux de complet. C'est vraiment ce qui fait de cette problématique.
Vous avez raison et j'avais tort ci-dessus. Vous devez alors utiliser asynchrone, par exemple,
async.parallel
, quand vous allez sur le tableau. Pour un exemple, voir ici: stackoverflow.com/q/26431257/1355058 où je voulais aussi passer les différents paramètres à tous les appels qui arrivent en parallèle. Maintenant, vous êtes fixé. 🙂Je vais vérifier la async module dans un peu plus en détail. Est-il une fonction particulière qui fonctionne bien avec la récursivité? Je vais avoir besoin le plus haut niveau
for
boucle pour terminer la dernière, donc, quand je lance le rappel (je peux passer la condition pour tester si elle est égale à startingPlace
), je suis dans le bon endroit?OriginalL'auteur AvocadoRivalry | 2014-10-22
Vous devez vous connecter pour publier un commentaire.
Dans votre exemple, vous n'avez pas d'appels récursifs. Si je comprends bien, vous voulez dire que
recurse(point, otherFunc);
est le début d'un appel récursif.Puis il suffit de revenir à la définition de l'appel récursif (que vous n'avez pas indiqué dans votre post) et le faire (ajouter un troisième argument en faveur d'une fonction de rappel à appeler à la fin de la récursivité; l'appelant va passer comme paramètre):
Puis dans le premier code que vous avez posté, faire appel à la place (dans le plus intérieur de la partie):
Juste passer un peu de temps et d'essayer de comprendre mon explication. Quand vous comprenez, alors vous connaîtrez ce nœud. C'est le nœud de la philosophie dans un post. J'espère que c'est clair. Votre premier exemple devrait ressembler à ceci:
Ci-dessous est uniquement des informations supplémentaires dans le cas où vous êtes intéressé. Sinon, vous avez défini ci-dessus.
Généralement dans node.js cependant, les gens retournent une valeur d'erreur, de sorte que l'appelant sait si la fonction a été appelée a terminé avec succès. Il n'y a pas de grand mystère ici. Au lieu de retourner à seulement
results
les gens font un appel de la formePuis dans l'autre fonction, vous pouvez avoir:
Mise à jour avec ma suggestion
C'est ma suggestion pour la fonction récursive, mais avant cela, il semble que vous devez définir vos propres
get
:Remarque que je suppose que la
get
demande de " bbb "est toujours suivi par unget
demande de "ccc". En d'autres termes, vous n'avez pas caché un point de retour pour les appels récursifs où vous avez les commentaires.if/else
- même si le tableau n'existe pas, il doit aller à travers tous les tableaux avant de les finir. Par exemple, si le startingPlace a trois endroits hors de lui, même si la première et la deuxième places étaient vides, il aurait encore à passer par la troisième place. Cela appelle la fonction de rappel la première fois qu'il arrive à un endroit vide.Ok, je vois maintenant pourquoi tu as eu le rappel lorsque vous vous l'avais mis au début. Dans le début de la boucle, vous aurez besoin d'une autre async pour les trois requêtes get. Chacun d'eux sera de retour d'une suite (éventuellement vide), mais tous les trois d'entre eux seront exécutés. Alors seulement vous voulez l'appeler la fonction de rappel et non là où je l'ai maintenant. Je suppose que vous voulez l'appeler ces fonctions dans l'ordre. Ensuite, essayez une variante de async comme la chute d'eau où vous pouvez également transmettre les résultats de l'un à l'autre.
En fait plus je pense que votre commentaire plus je ne sais pas ce que vous voulez vraiment faire. recurse effectue deux devient simple et potentiellement de nombreuses dans la troisième étape. Si l'un des points les résultats de tableau est vide, il suffit de ne pas faire l'appel récursif. La dernière option (ce qui est le plus probable) est d'utiliser les résultats de tableau comme point de départ pour une autre asynchrone.en parallèle appel, mais cette fois sur lit de façon récursive (pas myGet). Puis, quand tous retournent alors seulement vous avez la mention "retour callback2 ();" et éliminer le tout autre. Du sens?
C'est très semblable à un arbre. Chaque lieu a
x
nombre de lieux suivant. J'ai répéter au travers de chaque lieu, de faire unGET
demande pour chaque place à côté, etc. Enfin, une fois TOUS lesGET
demandes sont finis, je dois faire le dernier appel de la fonction. Le rappel n'est exécuté qu'une fois la dernière réponse est reçue, mais il n'y a pas d'informations où que le point d'arrêt est. J'ai suivi votre code, à l'aide deasync.parallel
, mais n'ont toujours pas eu de chance. Je se sentir comme il ya quelque chose de très fondamental, je suis absent ici. J'ai généralement eu aucun problème avec les rappels et async questions.A finalement été en mesure de résoudre ce à l'aide d'un autre
async
méthode - merci pour recommander le module!OriginalL'auteur MightyMouse
Généralement lorsque vous écrivez une fonction récursive, il va faire quelque chose et puis d'appeler lui-même ou de retour.
Vous devez définir
callback
dans le champ d'application de la fonction récursive (c'est à direrecurse
au lieu destart
), et vous avez besoin de l'appeler à l'endroit où vous auriez normalement de retour.Donc, un exemple hypothétique ressemblerait à quelque chose comme:
OriginalL'auteur Quentin
Je pense que vous pourriez trouver caolan/async utile. Regardez surtout dans
async.waterfall
. Il vous permettra de passer des résultats à partir d'un rappel de l'autre et quand c'est fait, faire quelque chose avec les résultats.Exemple:
OriginalL'auteur Juho Vepsäläinen
Si votre fonction récursive est synchrone, il suffit d'appeler la fonction de rappel sur la ligne suivante:
D'autre vous avez besoin de garder une référence à la fonction de rappel dans votre fonction récursive.
Passer le rappel comme un argument de la fonction et de l'appeler à chaque fois que c'est fini.
Voici la série complète de code. Je suis toujours avoir des problèmes avec la récursivité, où je ne peux pas obtenir le programme à attendre que toutes les boucles for et la récursivité à remplir avant d'appeler la fonction finale. À l'aide d'un setTimeout, tout marche bien, c'est certainement une question de l'asynchronicité, mais évidemment je ne peux pas aller dans cette voie. J'ai mis à jour le code ci-dessus avec plus de détails pour obtenir une aide supplémentaire.
OriginalL'auteur Bobby Marinoff
Construire votre code à partir de cet exemple:
OriginalL'auteur Augusto Federico Lemble