Ich benötige eine Schleife, die auf einen asynchronen Aufruf wartet, bevor ich fortfahre. Etwas wie:
for ( /* ... */ ) {
someFunction(param1, praram2, function(result) {
// Okay, for cycle could continue
})
}
alert("For cycle ended");
Wie könnte ich das machen? Hast du eine Idee?
javascript
Heirate Hoffser
quelle
quelle
( /* ... */ )
sieht aus wie ein Monster und ich habe jetzt Angst :(Antworten:
Sie können in JavaScript nicht synchron und asynchron mischen, wenn Sie das Skript blockieren, sondern den Browser blockieren.
Sie müssen hier den ganzen ereignisgesteuerten Weg gehen, zum Glück können wir das hässliche Zeug verstecken.
BEARBEITEN: Der Code wurde aktualisiert.
Dadurch erhalten wir eine asynchrone Funktion
loop
. Sie können diese natürlich noch weiter ändern, um beispielsweise eine Funktion zum Überprüfen des Schleifenzustands usw. zu verwenden.Nun zum Test:
Und die Ausgabe:
quelle
loop.break()
ich tun soll. Nur eine Möglichkeit, sich zu verdrängen, wenn Sie wollen?Ich habe das vereinfacht:
FUNKTION:
VERWENDUNG:
BEISPIEL: http://jsfiddle.net/NXTv7/8/
quelle
Eine sauberere Alternative zu dem, was @Ivo vorgeschlagen hat, wäre eine Warteschlange für asynchrone Methoden , vorausgesetzt, Sie müssen nur einen asynchronen Aufruf für die Sammlung ausführen.
( Eine ausführlichere Erklärung finden Sie in diesem Beitrag von Dustin Diaz.)
Sie erstellen einfach eine neue Instanz von
Queue
, fügen die erforderlichen Rückrufe hinzu und leeren die Warteschlange mit der asynchronen Antwort.Ein zusätzlicher Vorteil dieses Musters besteht darin, dass Sie der Warteschlange mehrere Funktionen hinzufügen können, anstatt nur eine.
Wenn Sie ein Objekt haben, das Iteratorfunktionen enthält, können Sie diese Warteschlange hinter den Kulissen unterstützen und Code schreiben, der synchron aussieht, aber nicht:
Schreiben Sie einfach,
each
um die anonyme Funktion in die Warteschlange zu stellen, anstatt sie sofort auszuführen, und leeren Sie die Warteschlange, wenn Ihr asynchroner Aufruf abgeschlossen ist. Dies ist ein sehr einfaches und leistungsstarkes Entwurfsmuster.PS Wenn Sie jQuery verwenden, steht Ihnen bereits eine asynchrone Methodenwarteschlange mit dem Namen jQuery.Deferred zur Verfügung .
quelle
someFunction
denen der Rest der Schleife verzögert wird. Ihr Muster erstellt eine Liste von Funktionen, die in der richtigen Reihenfolge ausgeführt werden und alle empfangen die Ergebnisse eines weiteren Funktionsaufrufs. Es ist ein gutes Muster, aber ich denke nicht, dass es zu der fraglichen Frage passt.setTimeout
. Sie riskieren unbeabsichtigtes Verhalten, wenn der Code schneller ausgeführt wird als erwartet.setTimeout
wenn der Rückruf nur die Hälfte der Zeit in Anspruch nimmt und der Code wieder schneller ausgeführt wird ... worum geht es also? Der "Code" in der "Schleife" ist immer noch in Ordnung. Wenn Sie vor dem vollständigen Rückruf einige Dinge außerhalb des "Rückrufs" ausführen, rufen Sie bereits nach Problemen, aber andererseits ist es ein Thread, ich habe es schwer, einen zu finden Szenario, in demsetTimeout
etwas kaputt gehen würde, ohne weitere Fehlentwürfe.Schauen Sie sich auch diese großartige Bibliothek caolan / async an . Ihre
for
Schleife kann einfach mit mapSeries oder Serien durchgeführt werden .Ich könnte einen Beispielcode posten, wenn Ihr Beispiel mehr Details enthält.
quelle
Wir können auch die Hilfe von jquery verwenden. In diesem Fall würde die asyncLoop-Funktion folgendermaßen aussehen:
Die Rückruffunktion sieht folgendermaßen aus:
Beispielfunktion, die verzögert auflöst:
quelle
Ich habe das "setTimeout (Func, 0)" verwendet. Trick für etwa ein Jahr. Hier sind einige aktuelle Forschungsergebnisse, die ich geschrieben habe, um zu erklären, wie man es ein bisschen beschleunigt. Wenn Sie nur die Antwort wünschen, fahren Sie mit Schritt 4 fort. In Schritt 1, 2 und 3 werden die Argumentation und die Mechanik erläutert.
quelle
Bei einer asynchronen Worker-Funktion
someFunction
, die eine Ergebnisfunktion mit einemresult
Argument zurückruft, das angibt, ob die Schleife fortgesetzt werden soll oder nicht:Um zu überprüfen, ob die Schleife beendet werden soll oder nicht, kann die Worker-Funktion
someFunction
die Ergebnisfunktion an andere asynchrone Operationen weiterleiten. Außerdem kann der gesamte Ausdruck in eine asynchrone Funktion eingekapselt werden, indem eine Funktiondone
als Rückruf verwendet wird.quelle
Wenn Ihnen die Antwort von wilsonpage gefällt, Sie jedoch eher an die Verwendung der Syntax von async.js gewöhnt sind, finden Sie hier eine Variation:
Die Demo finden Sie hier - http://jsfiddle.net/NXTv7/8/
quelle
Hier ist ein weiteres Beispiel, das meiner Meinung nach besser lesbar ist als andere, bei dem Sie Ihre asynchrone Funktion in eine Funktion einschließen, die eine
done
Funktion, den aktuellen Schleifenindex und das Ergebnis (falls vorhanden) des vorherigen asynchronen Aufrufs enthält:Sobald
done()
es aufgerufen wird, löst es den nächsten asynchronen Aufruf aus und übergibt erneut die Funktion done, den aktuellen Index und das vorherige Ergebnis. Sobald die gesamte Schleife abgeschlossen ist, wird die bereitgestellte Schleifecallback
aufgerufen.Hier ist ein Ausschnitt, den Sie ausführen können:
quelle
Sie können
async await
in ES7 eingeführt verwenden:Dies funktioniert nur, wenn
someFunction
ein Versprechen zurückgegeben wird!Wenn Sie
someFunction
ein Versprechen nicht zurückgeben, können Sie es selbst dazu bringen, ein Versprechen wie folgt zurückzugeben:Ersetzen Sie dann diese Zeile
await someFunction(param1, param2);
durchawait asynSomeFunction(param1, param2);
Bitte verstehe Versprechen, bevor du
async await
Code schreibst !quelle
Unexpected await inside loop
.javascript
Problem. Diese Warnung stammt aus Ihrereslint
Konfiguration. Ich deaktiviere diese Regel immer,eslint
weil ich an den meisten Stellen, die ich wirklich brauche, innerhalb der Schleife warten musshttp://cuzztuts.blogspot.ro/2011/12/js-async-for-very-cool.html
BEARBEITEN:
Link von Github: https://github.com/cuzzea/lib_repo/blob/master/cuzzea/js/functions/core/async_for.js
Mit dieser Funktion können Sie mit settings.limit eine prozentuale Unterbrechung in der for-Schleife erstellen. Die limit-Eigenschaft ist nur eine Ganzzahl, aber wenn sie als array.length * 0.1 festgelegt wird, wird die settings.limit_callback alle 10% aufgerufen.
Beispiel:
quelle
Eine vielversprechende bibliotheksbasierte Lösung:
quelle
Ich musste einige asynchrone Funktionszeiten aufrufen
X
, jede Iteration muss nach der vorherigen stattgefunden haben, also habe ich eine kleine Bibliothek geschrieben , die wie folgt verwendet werden kann:Jedes Mal, wenn eine benutzerdefinierte Schleifenfunktion aufgerufen wird, hat sie zwei Argumente, den Iterationsindex und den vorherigen Rückgabewert des Aufrufs.
Dies ist ein Beispiel für die Ausgabe:
quelle