Soweit ich weiß, funktioniert das Einfügen mehrerer await
Codes in ES7 / ES2016 ähnlich wie das Verketten .then()
mit Versprechungen, was bedeutet, dass sie nacheinander und nicht parallel ausgeführt werden. So haben wir zum Beispiel diesen Code:
await someCall();
await anotherCall();
Verstehe ich es richtig, dass anotherCall()
erst aufgerufen wird, wenn someCall()
es abgeschlossen ist? Was ist die eleganteste Art, sie parallel zu nennen?
Ich möchte es in Node verwenden, also gibt es vielleicht eine Lösung mit asynchroner Bibliothek?
BEARBEITEN: Ich bin mit der in dieser Frage bereitgestellten Lösung nicht zufrieden: Verlangsamung aufgrund des nicht parallelen Wartens auf Versprechen in asynchronen Generatoren , da Generatoren verwendet werden und ich nach einem allgemeineren Anwendungsfall frage.
quelle
await
würde warten, bis die erste Funktion abgeschlossen ist vollständig vor der Ausführung der zweiten.Promise
s. Die verknüpfte Frage betrifft die Bluebird-Bibliothek mit Generatoren und Ertrag. Konzeptionell vielleicht ähnlich, aber nicht in der Umsetzung.Antworten:
Sie können warten auf
Promise.all()
:So speichern Sie die Ergebnisse:
Beachten Sie, dass
Promise.all
dies schnell fehlschlägt. Dies bedeutet, dass das gesamte Objekt abgelehnt wird, sobald eines der ihm gegebenen Versprechen abgelehnt wird.Wenn Sie stattdessen darauf warten möchten, dass alle Versprechen erfüllt oder abgelehnt werden, können Sie sie verwenden
Promise.allSettled
. Beachten Sie, dass Internet Explorer diese Methode nicht nativ unterstützt.quelle
[result1, result2] = Promise.all([async1(), async2()]);
= await Promise.all
?TL; DR
Verwenden Sie
Promise.all
für die parallelen Funktionsaufrufe das Antwortverhalten nicht korrekt, wenn der Fehler auftritt.Führen Sie zunächst alle asynchronen Aufrufe gleichzeitig aus und erhalten Sie alle
Promise
Objekte. Zweitensawait
für diePromise
Objekte verwenden. Auf diese Weise werdenPromise
die anderen asynchronen Aufrufe fortgesetzt , während Sie darauf warten, dass der erste die anderen asynchronen Aufrufe auflöst. Insgesamt warten Sie nur so lange wie der langsamste asynchrone Anruf. Zum Beispiel:JSbin-Beispiel: http://jsbin.com/xerifanima/edit?js,console
Vorsichtsmaßnahme: Es spielt keine Rolle, ob sich die
await
Anrufe auf derselben Leitung oder auf verschiedenen Leitungen befinden, solange der ersteawait
Anruf nach allen asynchronen Anrufen erfolgt. Siehe JohnnyHKs Kommentar.Update: Diese Antwort hat ein anderes Timing bei der Fehlerbehandlung als die Antwort von @ bergi . Sie wirft den Fehler NICHT aus, wenn der Fehler auftritt, sondern nachdem alle Versprechen ausgeführt wurden. Ich vergleiche das Ergebnis mit @ jonnys Tipp:
[result1, result2] = Promise.all([async1(), async2()])
Überprüfen Sie das folgende Code-Snippetquelle
[someResult, anotherResult] = [await someResult, await anotherResult]
wenn Sie ändernconst
zulet
.await
Aussagen immer noch seriell aus, oder? Das heißt, die Ausführung wird angehalten, bis die erste aufgelöst istawait
, und geht dann zur zweiten über.Promise.all
wird parallel ausgeführt.Promise.all
. Wenn es sich bei jeder Anforderung um einen Netzwerkanruf handelt,await someResult
muss dieser gelöst werden, bevor erawait anotherResult
überhaupt gestartet wird. Umgekehrt können inPromise.all
den beidenawait
Aufrufen gestartet werden, bevor einer der beiden aufgelöst wird.Aktualisieren:
Die ursprüngliche Antwort macht es schwierig (und in einigen Fällen unmöglich), Versprechungen abzulehnen. Die richtige Lösung ist zu verwenden
Promise.all
:Ursprüngliche Antwort:
Stellen Sie einfach sicher, dass Sie beide Funktionen aufrufen, bevor Sie auf eine der beiden warten:
quelle
await
sie dann in tatsächliche Werte auflösen.Es gibt einen anderen Weg ohne Promise.all (), dies parallel zu tun:
Erstens haben wir zwei Funktionen zum Drucken von Zahlen:
Dies ist sequentiell:
Das ist parallel:
quelle
Dies kann mit Promise.allSettled () erreicht werden , das
Promise.all()
dem ausfallsicheren Verhalten ähnelt, jedoch ohne dieses ausfällt.Hinweis : Dies ist eine hochmoderne Funktion mit eingeschränkter Browserunterstützung. Ich empfehle daher dringend , für diese Funktion eine Polyfüllung hinzuzufügen.
quelle
Ich habe eine Übersicht erstellt , in der verschiedene Methoden zur Lösung von Versprechungen mit Ergebnissen getestet wurden. Es kann hilfreich sein, die Optionen anzuzeigen, die funktionieren.
quelle
Während das Setzen von p1, p2 und p3 sie nicht streng parallel ausführt, halten sie keine Ausführung auf und Sie können Kontextfehler mit einem Catch abfangen.
quelle
warte auf Promise.all ([someCall (), anotherCall ()]); Wie bereits erwähnt, fungiert es als Thread-Zaun (im parallelen Code als CUDA sehr häufig), sodass alle darin enthaltenen Versprechen ausgeführt werden können, ohne sich gegenseitig zu blockieren. Es wird jedoch verhindert, dass die Ausführung fortgesetzt wird, bis ALLE gelöst sind.
Ein weiterer Ansatz, der es wert ist, geteilt zu werden, ist die asynchrone Node.js-Methode, mit der Sie auch die Menge an Parallelität steuern können, die normalerweise wünschenswert ist, wenn die Aufgabe direkt mit der Verwendung begrenzter Ressourcen als API-Aufruf, E / A-Operationen, verknüpft ist. usw.
Credits für den Autor des Medium-Artikels ( lesen Sie mehr )
quelle
In meinem Fall habe ich mehrere Aufgaben, die ich parallel ausführen möchte, aber ich muss mit dem Ergebnis dieser Aufgaben etwas anderes tun.
Und die Ausgabe:
quelle
Ich stimme für:
Beachten Sie den Moment, in dem Sie Funktionen aufrufen. Dies kann zu unerwarteten Ergebnissen führen:
Das Folgen löst jedoch immer die Anforderung aus, einen neuen Benutzer zu erstellen
quelle
else
Block zu wickeln .Ich erstelle eine Hilfsfunktion waitAll, vielleicht kann sie süßer werden. Es funktioniert momentan nur in NodeJS , nicht in Browser Chrome.
quelle
for
Schleife wartet nacheinander auf jedes Versprechen und fügt das Ergebnis dem Array hinzu.