Node.js: la Meilleure façon d'effectuer de multiples opérations asynchrones, puis faire quelque chose d'autre?
Dans le code suivant, je suis en train de faire plusieurs (environ 10) les requêtes HTTP et RSS analyse d'un seul coup.
Je suis en utilisant le standard forEach
construire sur un tableau d'Uri j'ai besoin d'accéder et d'analyser le résultat de l'.
Code:
var articles;
feedsToFetch.forEach(function (feedUri)
{
feed(feedUri, function(err, feedArticles)
{
if (err)
{
throw err;
}
else
{
articles = articles.concat(feedArticles);
}
});
});
//Code I want to run once all feedUris have been visited
Je comprends que lorsque l'appel d'une fonction une fois que je devrais être en utilisant une fonction de rappel. Toutefois, la seule façon que je peux penser de l'utilisation d'un rappel dans cet exemple serait d'appeler une fonction qui compte le nombre de fois où il a été appelé et ne continue quand il a été appelé le même nombre de fois que feedsToFetch.length
qui semble hacky.
Donc ma question est, quelle est la meilleure façon de gérer ce type de situation node.js.
De préférence sans aucune forme de blocage! (J'ai encore envie que sa grande vitesse). Est-il des promesses ou quelque chose d'autre?
Grâce,
Danny
veuillez afficher le code pour le
feed()
fonction.c'est peut-être la préférence personnelle, mais je ne pense pas que les Promesses soient le plus "simple" de chemin à faire. J'ai apporté une réponse à étendre sur ce point.
Vous l'avez compris: l'utilisation d'un compteur et de compter le nombre de demandes présentées et complété. C'est fondamentalement ce que async et les promesses faites à l'interne. Environ un an avant la async bibliothèque a été écrit, j'ai écrit cette réponse pour résoudre ce problème: stackoverflow.com/questions/4631774/... . C'est un plus avancées de mise en œuvre qui permet de lancer des lots d'opérations asynchrones: stackoverflow.com/questions/13250746/...
Je dirais préférence personnelle, je ne vois pas aarosil de répondre beaucoup plus complexe que la vôtre.
OriginalL'auteur dannybrown | 2014-10-09
Vous devez vous connecter pour publier un commentaire.
HACK-GRATUIT SOLUTION
Promet d'être inclus dans la prochaine version JavaScript
Le populaire Promesse bibliothèques de vous donner un
.all()
méthode exacte de ce cas d'utilisation (en attente pour un tas d'appels asynchrones à compléter, puis de faire autre chose). C'est le match parfait pour votre scénarioBluebird a également
.map()
, ce qui peut prendre un tableau de valeurs et l'utiliser pour démarrer une Promesse de la chaîne.Voici un exemple d'utilisation de Bluebird
.map()
:Notez également que vous n'avez pas besoin d'utiliser cette fermeture d'accumuler les résultats.
La Bluebird API Docs sont vraiment bien écrit aussi, avec beaucoup d'exemples, si elle rend plus facile à récupérer.
Une fois que j'ai appris Promesse de modèle, il a rendu la vie tellement plus facile. Je ne peux pas le recommander assez.
Aussi, ici, est un article sur les différentes méthodes pour composer avec async fonctions à l'aide de promesses, le
async
module, et d'autresEspérons que cette aide!
+1 lol bon travail ^.^
OriginalL'auteur aarosil
Pas de hacks nécessaire
Je vous conseille d'utiliser le asynchrone module, il rend ces sortes de choses beaucoup plus facile.
async
fournit async.eachSeries comme un async remplacement pourarr.forEach
et vous permet de passer undone
fonction de rappel quand il est complet. Il permettra de traiter chacun de ces éléments dans une série, tout commeforEach
. Aussi, il sera idéalement bulle erreurs de rappel, de sorte que vous n'avez pas besoin de gestionnaire de la logique à l'intérieur de la boucle. Si vous voulez/besoin parallèle de traitement, vous pouvez utiliser async.chaque.Il y aura aucun blocage entre les
async.eachSeries
appel et le rappel.Sinon, vous pourriez construire un tableau des opérations asynchrones et de les transmettre à async.série. La série traitera vos résultats dans un série (non parallèles) et d'appeler la fonction de rappel lorsque chaque fonction est terminée. La seule raison d'utiliser ce fil
async.eachSeries
serait si vous avez préféré le familierarr.forEach
syntaxe.Ou vous pouvez Rouler Vos Propres™
Peut-être, vous vous sentez supplémentaire ambitieux ou peut-être vous ne voulez pas compter sur la
async
de dépendance. Peut-être vous êtes juste ennuyé comme je l'étais. De toute façon, j'ai volontairement copié l'API deasync.eachSeries
pour le rendre facile à comprendre comment cela fonctionne.Une fois que nous supprimer les commentaires ici, nous avons juste 9 lignes de code qui peuvent être réutilisés pour tout tableau que l'on veut traiter de manière asynchrone! Il ne sera pas modifier le tableau d'origine, des erreurs peuvent être envoyées à "court-circuit" de l'itération, et séparé de rappel peuvent être utilisés. Il permettra également de travailler sur des tableaux vides. Un peu de fonctionnalité pour seulement 9 lignes 🙂
Maintenant, nous allons créer un exemple de fonction async à utiliser avec elle. Nous allons faux le retard avec un
setTimeout
de 500 ms ici.Ok, nous allons voir comment ils travaillent !
De sortie (500 ms de retard avant chaque sortie)
la note est node/v8 vNext, il aura de rendement. Recherche pour cela.
le asyncEach ici se comporte plus comme
async.eachSeries
queasync.each
fwiw.async.each
va déclencher des requêtes http (ou autre) aussi vite qu'il le peut, c'est à dire simultanément;asynSeries
(ou de la "série" solution ici) de le faire l'un après l'autre. Si je ne me Trompe.bonne prise. J'ai renommé la coutume
asyncEach
àasyncForEach
à penser qu'il n'série de traitement commearr.forEach
. J'ai aussi mis à jour leasync.each
àasync.eachSeries
. Merci !Donc quand vous dites que le nœud "est livré avec" Promet de vous dire "si vous utilisez le dernière unstable de libération, et assurez-vous de le faire fonctionner avec la
--harmony
interrupteur pour activer les fonctions expérimentales, [noeud de navires avec des promesses]"? C'est une très particulière de la définition de "pas de hacks" et de "navires avec" 🙂 d'ailleurs c'est drôle que vous devriez dire "depuis" depuis la version que vous avez nommé la toute dernière tagged unstable.OriginalL'auteur user633183
à l'aide d'une copie de la liste des url comme une file d'attente pour suivre les arrivées en fait simple:
(toutes les modifications de commentaire)
en fin de compte, ce n'est pas beaucoup plus "sale" que des promesses, et vous offre la possibilité de recharger non-fini url (un seul compteur ne vais pas vous dire lequel(s) a échoué). pour cette simple parallèle tâche de téléchargement, il va vraiment ajouter plus de code à votre projet de mettre en œuvre les Promesses qu'une simple file d'attente, et de la Promesse.tous les() n'est pas la plus intuitive lieu de tomber à travers. Une fois que vous obtenez dans les sous-sous-requêtes, ou souhaitez une meilleure gestion des erreurs qu'un trainwreck, je recommande fortement d'utiliser des Promesses, mais vous n'avez pas besoin d'un lance-roquettes pour tuer un écureuil...
OriginalL'auteur dandavis