Ich habe zwei JS-Funktionen. Einer ruft den anderen an. Innerhalb der aufrufenden Funktion möchte ich die andere aufrufen, warten, bis diese Funktion beendet ist, und dann fortfahren. Also zum Beispiel / Pseudocode:
function firstFunction(){
for(i=0;i<x;i++){
// do something
}
};
function secondFunction(){
firstFunction()
// now wait for firstFunction to finish...
// do something else
};
Ich habe diese Lösung gefunden, weiß aber nicht, ob dies ein kluger Weg ist.
var isPaused = false;
function firstFunction(){
isPaused = true;
for(i=0;i<x;i++){
// do something
}
isPaused = false;
};
function secondFunction(){
firstFunction()
function waitForIt(){
if (isPaused) {
setTimeout(function(){waitForIt()},100);
} else {
// go do that thing
};
}
};
Ist das echt? Gibt es eine elegantere Art, damit umzugehen? Vielleicht mit jQuery?
firstFunction
genau macht es asynchron? So oder so - überprüfen Sie über VersprechenAntworten:
Eine Möglichkeit, mit asynchroner Arbeit wie dieser umzugehen, ist die Verwendung einer Rückruffunktion, z.
Gemäß dem Vorschlag von @Janaka Pushpakumara können Sie jetzt Pfeilfunktionen verwenden, um dasselbe zu erreichen. Beispielsweise:
firstFunction(() => console.log('huzzah, I\'m done!'))
Update: Ich habe dies vor einiger Zeit beantwortet und möchte es wirklich aktualisieren. Rückrufe sind zwar in Ordnung, führen jedoch meiner Erfahrung nach zu Code, der schwieriger zu lesen und zu warten ist. Es gibt Situationen, in denen ich sie immer noch verwende, z. B. um laufende Ereignisse und dergleichen als Parameter zu übergeben. Dieses Update dient nur zur Hervorhebung von Alternativen.
Auch die ursprüngliche Frage ist specificallty nicht async erwähnen, so falls jemand verwirrt ist, wenn Ihre Funktion synchron ist, es wird blockiert , wenn sie aufgerufen. Beispielsweise:
Wenn die Funktion, wie impliziert, asynchron ist, ist die Art und Weise, wie ich heute mit all meiner asynchronen Arbeit umgehe, asynchron / warten. Beispielsweise:
IMO, async / await macht Ihren Code viel lesbarer als die direkte Verwendung von Versprechungen (meistens). Wenn Sie mit Fangfehlern umgehen müssen, verwenden Sie sie mit try / catch. Lesen Sie hier mehr darüber: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function .
quelle
Verwenden Sie async / await:
Verwenden Sie dann await in Ihrer anderen Funktion, um auf die Rückkehr zu warten:
quelle
$(function() { await firstFunction(); secondFunction(); });
?await
kann nur innerhalb einerasync
Methode verwendet werden. Wenn Sie also Ihre übergeordnete Funktionasync
aktivieren, können Sie beliebig vieleasync methods
Benutzer mit oder ohne Funktion aufrufenawait
.await
einemsetTimeout
?Anscheinend fehlt Ihnen hier ein wichtiger Punkt: JavaScript ist eine Single-Threaded-Ausführungsumgebung. Schauen wir uns Ihren Code noch einmal an. Beachten Sie, dass ich Folgendes hinzugefügt habe
alert("Here")
:Sie müssen nicht warten
isPaused
. Wenn Sie die Warnung "Hier" sehen,isPaused
wird siefalse
bereits angezeigt undfirstFunction
ist zurückgekehrt. Das liegt daran, dass Sie nicht innerhalb derfor
Schleife (// do something
) "nachgeben" können. Die Schleife wird möglicherweise nicht unterbrochen und muss zuerst vollständig abgeschlossen werden (weitere Details: Javascript-Thread-Behandlung und Race-Bedingungen ).Trotzdem können Sie den Codefluss im Inneren
firstFunction
asynchron gestalten und entweder Rückruf oder Versprechen verwenden, um den Anrufer zu benachrichtigen. Sie müssten diefor
Schleife aufgeben undif
stattdessen mit simulieren ( JSFiddle ):Nebenbei bemerkt hat JavaScript 1.7
yield
Schlüsselwörter als Teil von Generatoren eingeführt . Dadurch können asynchrone Löcher in den ansonsten synchronen JavaScript-Codefluss "gestanzt" werden ( weitere Details und ein Beispiel ). Die Browserunterstützung für Generatoren ist derzeit jedoch auf Firefox und Chrome, AFAIK, beschränkt.quelle
Eine elegante Möglichkeit, darauf zu warten, dass eine Funktion zuerst ausgeführt wird, besteht darin, Promises mit der Funktion async / await zu verwenden.
setTimeout
, um die Situation zu demonstrieren, in der die Ausführung der Anweisungen einige Zeit in Anspruch nehmen würde.await
um die erste Funktion abzuschließen, bevor Sie mit den Anweisungen fortfahren.Beispiel:
Hinweis:
Sie könnten einfach
resolve
dasPromise
ohne irgendeinen Wert soresolve()
. In meinem Beispiel habe ichresolved
denPromise
mit dem Werty
, den ich dann in der zweiten Funktion verwenden kann.quelle
Das einzige Problem mit Versprechungen ist, dass der IE sie nicht unterstützt. Edge tut es, aber es gibt viele IE 10 und 11 da draußen: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise (Kompatibilität unten)
JavaScript ist also Single-Threaded. Wenn Sie keinen asynchronen Anruf tätigen, verhält sich dieser vorhersehbar. Der Haupt-JavaScript-Thread führt eine Funktion vollständig aus, bevor die nächste in der Reihenfolge ausgeführt wird, in der sie im Code angezeigt werden. Die Garantie der Reihenfolge für synchrone Funktionen ist trivial - jede Funktion wird vollständig in der Reihenfolge ausgeführt, in der sie aufgerufen wurde.
Stellen Sie sich die synchrone Funktion als atomare Arbeitseinheit vor . Der Haupt-JavaScript-Thread führt es vollständig aus, in der Reihenfolge, in der die Anweisungen im Code erscheinen.
Aber werfen Sie den asynchronen Aufruf wie in der folgenden Situation ein:
Das macht nicht was du willst . Es führt sofort Funktion 1, Funktion 2 und Funktion 3 aus. Das Laden von div blinkt und ist weg, während der Ajax-Aufruf bei weitem nicht abgeschlossen ist, obwohl er
makeAjaxCall()
zurückgekehrt ist. Die Komplikation ist, dassmakeAjaxCall()
die Arbeit in Blöcke aufgeteilt wurde , die nach und nach durch jede Drehung des Haupt-JavaScript-Threads erweitert werden - sie verhält sich asychron. Derselbe Haupt-Thread führte jedoch während eines Drehs / Laufs die synchronen Teile schnell und vorhersehbar aus.So habe ich damit umgegangen : Wie gesagt, die Funktion ist die atomare Arbeitseinheit. Ich habe den Code von Funktion 1 und 2 kombiniert - ich habe den Code von Funktion 1 vor dem asynchronen Aufruf in Funktion 2 eingefügt. Ich habe Funktion 1 losgeworden. Alles bis einschließlich des asynchronen Aufrufs wird vorhersehbar in der richtigen Reihenfolge ausgeführt.
Wenn der asynchrone Aufruf abgeschlossen ist, rufen Sie nach mehreren Drehungen des JavaScript-Hauptthreads die Funktion 3 auf. Dies garantiert die Reihenfolge . Mit ajax wird beispielsweise der Ereignishandler onreadystatechange mehrmals aufgerufen. Wenn es meldet, dass es abgeschlossen ist, rufen Sie die gewünschte endgültige Funktion auf.
Ich bin damit einverstanden, dass es chaotischer ist. Ich mag es, wenn Code symmetrisch ist, ich mag es, wenn Funktionen eine Sache tun (oder in der Nähe davon), und ich mag es nicht, wenn der Ajax-Aufruf in irgendeiner Weise für die Anzeige verantwortlich ist (wodurch eine Abhängigkeit vom Aufrufer entsteht). ABER bei einem in eine synchrone Funktion eingebetteten asynchronen Aufruf müssen Kompromisse eingegangen werden, um die Ausführungsreihenfolge zu gewährleisten. Und ich muss für IE 10 codieren, also keine Versprechen.
Zusammenfassung : Bei synchronen Anrufen ist die Garantie der Bestellung trivial. Jede Funktion wird vollständig in der Reihenfolge ausgeführt, in der sie aufgerufen wurde. Bei einer Funktion mit einem asynchronen Aufruf besteht die einzige Möglichkeit, die Reihenfolge zu gewährleisten, darin, zu überwachen, wann der asynchrone Aufruf abgeschlossen ist, und die dritte Funktion aufzurufen, wenn dieser Status erkannt wird.
Eine Diskussion der JavaScript-Threads finden Sie unter: https://medium.com/@francesco_rizzi/javascript-main-thread-dissected-43c85fce7e23 und https://developer.mozilla.org/en-US/docs/Web/JavaScript/ EventLoop
Eine weitere ähnliche, hoch bewertete Frage zu diesem Thema: Wie soll ich 3 Funktionen aufrufen, um sie nacheinander auszuführen?
quelle
Das habe ich mir ausgedacht, da ich mehrere Operationen in einer Kette ausführen muss.
quelle
Ihr Hauptspaß wird zuerstFun nennen, und wenn Sie fertig sind, wird Ihr nächster Spaß anrufen.
quelle