Node.js: Beste Weg, um mehrere asynchrone Operationen, dann etwas anderes tun?
Im folgenden code versuche ich, mehrere (etwa 10) HTTP-Anfragen und RSS-analysiert in einem Rutsch.
Ich bin mit dem standard - forEach
Konstrukt auf ein array von URIs, die ich brauche, um Zugang und analysieren das Ergebnis.
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
Ich verstehe, dass, wenn Sie eine Funktion aufrufen, sobald ich mit sollte ein Rückruf. Jedoch, die einzige Möglichkeit die ich denken kann mit einem Rückruf wäre in diesem Beispiel zu nennen, eine Funktion, die zählt, wie oft es aufgerufen wurde und nur fortgesetzt wird, wenn es aufgerufen wurde die gleiche Menge an Zeiten, als feedsToFetch.length
scheint hacky.
Also meine Frage ist, was ist der beste Weg, zu behandeln diese Art von situation, in node.js.
Vorzugsweise ohne irgendeine form von Sperrung! (Ich will immer noch rasend schneller Geschwindigkeit). Ist es verspricht oder etwas anderes?
Dank,
Danny
- Ja, Versprechen sind der einfachste Weg zu gehen. Wenn Sie lieber Kochen Sie sich Ihre eigene Lösung mit standard-JS diese Antwort von mir leicht angepasst werden kann.
- bitte zeigen Sie den code für die
feed()
Funktion. - vielleicht ist es persönliche Präferenz, aber ich glaube nicht, dass die Versprechen der "einfachste" Weg zu gehen. Ich habe eine Antwort zu erweitern.
- Sie haben es herausgefunden: verwenden Sie einen Zähler und zählt die Anzahl der Anfragen gemacht und abgeschlossen. Es ist im Grunde, was async und Versprechen tun Sie intern. Etwa ein Jahr vor dem async-Bibliothek geschrieben wurde, schrieb ich diese Antwort zu lösen genau dieses problem: stackoverflow.com/questions/4631774/... . Dies ist eine erweiterte Implementierung, ermöglicht den Start-batches von asynchronen Operationen: stackoverflow.com/questions/13250746/...
- Ich würde sagen, persönliche Vorliebe - ich sehe nicht, aarosil die Antwort viel komplexer als deins.
- ist es für Sie wichtig, was, um den Artikel am Ende in? Die
serial
option von @naomik unten ist das einzige, das erhalten der Bestellung, wenn ich mich nicht Irre. - mit dem Versprechen, dass wäre eine standard-for-Schleife... verspricht eine tatsächliche Abstraktion auf die Sequenzierung Dinge - es ist viel mehr sound und vollständiger als die 'async' - Modul, die meisten modernen Sprachen haben Sie unter verschiedenen Namen und Sie waren weit verbreitet.
- ist weit verbreitet [alles außer IE]". Ich mag, wie Sie Kritik meine Antwort für die Verwendung einer lib komplett mit Blick auf die Tatsache, dass ich, sofern ein roll-your-own-Lösung als gut. Zur gleichen Zeit, Sie sind im Grunde sagen "etwas verwenden, ist nicht unterstützt in IE oder Holen Sie sich ein polyfill (siehe: "lib")".
- Ich stehe korrigiert-- .Karte bewahrt Ordnung.
Du musst angemeldet sein, um einen Kommentar abzugeben.
HACK-FREIE LÖSUNG
Verspricht, enthalten in der nächsten JavaScript-version
Populären Versprechen Bibliotheken geben Ihnen einen
.all()
Methode für diese genaue Verwendung Fall (warten auf eine Reihe von asynchronen Aufrufe abgeschlossen ist, dann etwas anderes zu tun). Es ist die perfekte Ergänzung für Ihr SzenarioBluebird hat auch
.map()
, die ein array von Werten, und es verwenden, um zu beginnen, ein Versprechen Kette.Hier ist ein Beispiel mit Bluebird
.map()
:Beachten Sie auch, dass Sie nicht brauchen, um verwenden Schließung hier zu sammeln die Ergebnisse.
Den Bluebird-API-Docs sind wirklich gut geschrieben, auch mit vielen Beispielen, so dass es macht es leichter zu Holen.
Einmal habe ich gelernt, Versprechen, Muster, es machte das Leben so viel einfacher. Ich kann es nicht genug empfehlen.
Auch, hier ist ein toller Artikel über verschiedene Ansätze zum Umgang mit asynchronen Funktionen, die mit Versprechungen, die
async
Modul, und andereHoffe, das hilft!
Keine hacks notwendig
Ich würde empfehlen, mit der async - Modul, wie es macht diese Dinge viel einfacher.
async
bietet async.eachSeries als asynchrone Ersatz fürarr.forEach
und ermöglicht die übergabe einesdone
callback-Funktion, wenn es fertig ist. Es wird die Verarbeitung der einzelnen Elemente in einer Reihe, so wieforEach
tut. Es ist auch bequem bubble Fehler auf Ihren Rückruf, so dass Sie nicht haben, um handler-Logik innerhalb der Schleife. Wenn Sie möchten/benötigen parallel Verarbeitung, die Sie verwenden können,async.jeder.Wird es keine Blockierung zwischen den
async.eachSeries
Anruf und dem Rückruf.Alternativ können Sie erstellen eine Reihe von asynchronen Operationen, und übergeben Sie an async.Serie. Serie verarbeiten Ihre Ergebnisse in einem Serie (nicht parallel) und rufe den callback, wenn jede Funktion abgeschlossen ist. Der einzige Grund, dies nicht über
async.eachSeries
wäre, wenn Sie bevorzugt das vertrautearr.forEach
syntax.Oder Sie können Roll your Own™
Vielleicht haben Sie das Gefühl zusätzliche ehrgeizig oder vielleicht haben Sie nicht wollen, verlassen Sie sich auf die
async
Abhängigkeit. Vielleicht sind Sie nur gelangweilt wie ich war. Jedenfalls habe ich absichtlich kopiert die API vonasync.eachSeries
machen es einfach, zu verstehen, wie das funktioniert.Einmal entfernen wir die Kommentare hier, wir haben nur 9 Zeilen code, die wiederverwendet werden können, für alle Arrays wir wollen den Prozess asynchron! Es wird sich nicht ändern, das ursprüngliche array, Fehler können geschickt werden an "Kurzschluss" der iteration, und eine separate callback genutzt werden können. Es funktioniert auch bei leeren arrays. Einiges an Funktionalität für nur 9 Zeilen 🙂
Nun erstellen wir eine Beispiel-async-Funktion zu verwenden, mit es. Wir werden fake die Verzögerung mit einem
setTimeout
von 500 ms hier.Ok, lasst uns sehen, wie Sie funktionieren !
Ausgang (500 ms Verzögerung vor jeder Ausgabe)
async.eachSeries
alsasync.each
fwiw.async.each
wird das Feuer aus den http-Anfragen (oder was auch immer) so schnell wie möglich, d.h. gleichzeitig;asynSeries
(oder die "serielle" Lösung hier) wird einer nach dem nächsten. Wenn ich mich nicht Irre.asyncEach
zuasyncForEach
zu implizieren, dass es nicht eine serielle Verarbeitung wiearr.forEach
. Ich habe auch aktualisiert, dieasync.each
zuasync.eachSeries
. Danke !ReferenceError: Promise is not defined
. Das ist ein feature. Fügen Sie einfachbluebird
und alle Ihre Probleme Weg.--harmony
Schalter zum aktivieren der experimentellen Funktionen, [node Schiffe mit verspricht]"? Dies ist eine sehr eigenartige definition von "no hacks" und "Schiffe mit" 🙂 Übrigens es ist lustig sollten Sie sagen, "seit etwa" seit der Veröffentlichung haben Sie den Namen das neueste tagged unstable-release.durch eine Kopie der Liste der url wie eine Schlange zu verfolgen, Ankunft macht es einfach:
(alle änderungen kommentiert)
in das Ende, das ist nicht viel "schmutziger" als verspricht, und bietet Ihnen die chance, um neu zu laden un-fertige urls (ein Zähler alleine sage Ihnen, was man(N) fehlgeschlagen). für diese einfache parallel-download-Aufgabe, es ist eigentlich Los, um weitere code hinzufügen, um Ihr Projekt umzusetzen Verspricht, als eine einfache Warteschlange, und Versprechen.alle() ist nicht in den meisten intuitive Platz zu stolpern. Wenn man einmal in sub-sub-Abfragen, oder wollen eine bessere Fehlerbehandlung als ein trainwreck, ich dringend empfehlen, mit Versprechungen, aber Sie brauchen nicht eine Rakete launcher zu töten, ein Eichhörnchen...