async pour la boucle dans node.js
Je suis nouveau sur ce node.js ..je suis un peu peu confus au sujet de ce rappel..Dans mon application à l'intérieur d'une boucle for, je vais appeler un asynchrones appel de fonction,je pense que mon problème est que, avant que je reçois la réponse de l'appel asynchrone ma boucle pour obtenir en boucle.
Mon code:
async.forEach(Object.keys(config), function(key, next) {
search(config[key].query, function(err, result) { //
console.log("fffffffffff="+ util.inspect(result))-------- >>>Getting undefined..
if (err) return next(err) //
var json = JSON.stringify({
"result": result
});
results[key] = {
"result": result
}
console.log("rrrrrrrr="+util.inspect(results[key]))
next() //<---- critical piece. This is how the forEach knows to continue to the next loop. Must be called inside search's callback so that it doesn't loop prematurely.
})
},
function(err) {
console.log('iterating done');
res.writeHead(200, {
'content-type': 'application/json'
});
res.end(JSON.stringify(results));
});
}
Fonction de recherche de code:
var matches = [];
var qrySubString = query.substring(0, 4);
client.query("select * from xxxxxxxxx where level4 ILIKE '%" + query + "%'", function(err, row1, fields) {
for (var id in row1.rows) {
var match, name;
if (query == row1.rows[id].level4) {
match = true;
name = row1.rows[id].level4;
}
else {
match = false;
name = query;
}
matches.push({
"id": id,
"name": row1.rows[id].level4,
"score": 100,
"match": match,
"type": [{
"id": "/people/presidents",
"name": "US President"
}]
})
}
callback(matches);
})
Je veux exécuter pour la boucle après l'exécution réussie de 1 de la fonction recherche,je pense que je dois utiliser asynchrone pour la boucle.Merci de me guider pour résoudre ce..Merci d'avance..
Vous devez vous connecter pour publier un commentaire.
J'ai réduit l'exemple de code pour les lignes suivantes pour le rendre plus facile à comprendre l'explication de ce concept.
Le problème avec le code précédent est que le
search
fonction est asynchrone, donc quand la boucle est terminée, aucune des fonctions de rappel ont été appelés. Par conséquent, la liste deresults
est vide.Pour résoudre le problème, vous devez mettre le code après la boucle dans la fonction de callback.
Cependant, puisque la fonction de rappel est appelée plusieurs fois (une fois pour chaque itération), vous devez en quelque sorte savoir que tous les rappels ont été appelés. Pour ce faire, vous devez compter le nombre de rappels, et de vérifier si le nombre est égal au nombre de fonctions asynchrones appels.
Pour obtenir une liste de toutes les touches, utilisez
de l'Objet.les touches
. Ensuite, pour itérer sur cette liste, j'utilise.forEach
(vous pouvez également utiliserfor (var i = 0, key = keys[i]; i < keys.length; ++i) { .. }
, mais qui pourrait donner des problèmes, voir JavaScript à l'intérieur fermeture à boucle – simple exemple pratique).Voici un exemple complet:
Remarque: Le code asynchrone dans l'exemple précédent, sont exécutées en parallèle. Si les fonctions doivent être appelées dans un ordre spécifique, vous pouvez utiliser la récursivité pour obtenir l'effet désiré:
Ce que j'ai indiqué sont les concepts, vous pouvez utiliser l'un des nombreux (troisième partie) NodeJS modules de la mise en œuvre, tels que async.
onComplete
est appelé.--tasksToGo
après l'instruction if. SinononComplete
sera appelé un début.tasksToGo = keys.length = 1
. Après avoir terminé la tâche,--tasksToGo == 0
sera vrai, etonComplete
est appelé. S'il y a 2 éléments, la pré-incrémentation de l'opérateur donnerait 1, ce qui n'est pas 0 et donc la fonction de rappel n'est pas trop tôt.Vous avez le bon diagnostic de votre problème, si bon travail. Une fois que vous appelez dans votre recherche de code, la boucle continue juste à droite sur cours.
Je suis un grand fan de https://github.com/caolan/async, et il me sert bien. Fondamentalement, vous auriez retrouver avec quelque chose comme:
J'espère que ça aide!
search
. Le rappel que j'ai écrit s'attend à une erreur de l'objet comme premier paramètre et non pas les résultats de l'objet. Si vous prenez cette approche pour le faire, vous aurez besoin de changer votre ` callback(matches); appel à quelque chose comme ` callback(err,matches);`. Ensuite, l'appelant pouvait regarder l'objet d'erreur.next
à l'intérieur, cela devrait fonctionner. Il n'est pas nécessaire que la fonction d'être nomménext
. Cela dit, la nidification comme celle-là pourrait s'arracher les cheveux. Avez-vous une idée de ce que vous essayez de faire? Il y a peut être un moyen plus lisible pour le structurer. Voici un résumé illustrant les 2 choses que j'ai mentionnées ci-dessus: gist.github.com/juanpaco/046c1b580bc5de1742927c2d29d655f0J'aime utiliser le modèle récursif pour ce scénario. Par exemple, quelque chose comme ceci:
processQueries
est une fonction récursive qui va tirer une requête élément d'un tableau de requêtes à traiter. La fonction de rappel des appelsprocessQueries
de nouveau lorsque la requête est terminée. LeprocessQueries
sait à la fin quand il n'y a pas de requêtes de gauche.Il est plus facile de le faire à l'aide de tableaux, mais il pourrait être modifié pour fonctionner avec l'objet de clés/valeurs, j'imagine.
Node.js
introduitasync await
dans7.6
donc ce qui faitJavascript
plus belle.Pour que cela fonctionne
search
fucntion doit retourner unpromise
ou elle doit êtreasync
fonctionSi ce n'est pas le retour d'un
Promise
vous pouvez l'aider à retourner unPromise
Puis remplacez cette ligne
await search(query);
parawait asyncSearch(query);