Wie Sie warten, bis der JavaScript-Versprechen zu beheben, bevor Sie die Funktion wieder aufnimmt?
Mache ich einige unit-Tests. Das test-framework lädt eine Seite in einem iFrame und läuft dann Behauptungen gegen die Seite. Vor jedem test beginnt, erstelle ich ein Promise
wird der iFrame ist onload
Ereignis aufrufen resolve()
ist, setzt das iFrame -src
, und gibt das Versprechen.
So, ich kann nur rufen loadUrl(url).then(myFunc)
, und wird es warten, bis die Seite geladen ist, bevor Sie ausgeführt wird, was myFunc
ist.
Ich diese Art von Muster ganz über dem Platz in meinen tests (nicht nur für das laden von URLs), in Erster Linie, um zu erlauben, änderungen an der DOM zu passieren (z.B. imitieren klicken auf eine Schaltfläche und warten Sie, bis divs ein-und ausblenden).
Der Nachteil dieser Konstruktion ist, dass ich ständig schreiben anonyme Funktionen mit ein paar Zeilen code in Ihnen. Weiter, während ich einen work-around (QUnit ist assert.async()
), die test-Funktion, die definiert, die Versprechen, die abgeschlossen wird, bevor der Verheißung führen.
Frage ich mich, ob es irgendeinen Weg gibt, um einen Wert aus einer Promise
oder warten (block/sleep), bis es sich aufgelöst hat, ähnlich .NET IAsyncResult.WaitHandle.WaitOne()
. Ich weiß, JavaScript ist single-threaded, aber ich hoffe, dass bedeutet nicht, dass eine Funktion nicht nachgeben.
Im wesentlichen, ist es ein Weg, um die folgenden ausspucken Ergebnisse in der richtigen Reihenfolge?
JS:
function kickOff() {
return new Promise(function(resolve, reject) {
$("#output").append("start");
setTimeout(function() {
resolve();
}, 1000);
}).then(function() {
$("#output").append(" middle");
return " end";
});
};
function getResultFrom(promise) {
//todo
return " end";
}
var promise = kickOff();
var result = getResultFrom(promise);
$("#output").append(result);
HTML:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="output"></div>
- wenn Sie die append-Aufrufe in eine wiederverwendbare Funktion, können Sie dann (), wie erforderlich, um zu TROCKNEN. Sie können auch multi-purpose-Handler, gelenkt von diesen zu ernähren, dann () - Aufrufe, wie
.then(fnAppend.bind(myDiv))
, das kann zu einer erheblichen Senkung der anons. - Was du testen mit? Wenn es einen modernen browser, oder Sie können verwenden Sie ein tool wie BabelJS zu transpile Ihr code ist dies sicherlich möglich.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die aktuelle generation von Javascript im Browser nicht über eine
wait()
odersleep()
, die ermöglicht, dass die Dinge laufen. So, Sie können nicht einfach tun, was Sie gefragt haben. Stattdessen hat es async-Operationen, die machen Ihr Ding und dann rufen Sie an, wenn Sie fertig sind (wie Sie bisher verspricht).Teil davon ist, weil Javascript single-threadedness. Wenn die single-thread dreht, dann keine anderen Javascript ausführen kann, bis das Spinnen-thread ist fertig. ES6 führt
yield
und Generatoren, die es erlauben, einige kooperative tricks wie, dass, aber wir sind ziemlich weit in der Lage, Sie zu verwenden diese in einem breiten swatch der installierten Browser (Sie können verwendet werden, in einigen server-side Entwicklung, wo Sie Steuern die JS-engine, die verwendet wird).Sorgfältiger Umgang mit den promise-basierten code kann die Reihenfolge der Ausführung für viele asynchrone Operationen.
Ich bin mir nicht sicher, ob ich verstehe genau, was um Sie zu erreichen versuchen, in Ihrem code, aber Sie konnte etwas tun, wie diese mit Ihrem bestehenden
kickOff()
Funktion, und dann das anbringen einer.then()
- handler, der nach Aufruf:Zurückkehren Ausgang in einer garantierten Reihenfolge - so:
Update im Jahr 2018 (drei Jahre nach dieser Antwort geschrieben wurde):
Wenn Sie entweder transpile code, oder führen Sie Ihren code in einer Umgebung, unterstützt ES7 Funktionen wie
async
undawait
können Sie jetztawait
um Ihren code zu "erscheinen" auf das Ergebnis warten ein Versprechen. Es ist noch in der Entwicklung, mit dem Versprechen. Es tut immer noch nicht alle blockieren von Javascript, aber es erlaubt Ihnen, zu schreiben, sequenzielle Operationen in eine freundlichere syntax.Anstelle des ES6 Weg, Dinge zu tun:
Können Sie dies tun:
then()
ist, was ich Tue. Ich weiß einfach nicht, wie mit schreibenfunction() { ... }
alle Zeit. Es clutters den code.(foo) => { ... }
stattfunction(foo) { ... }
foo => single.expression(here)
um loszuwerden, geschweifte und Runde Klammern.async
undawait
syntax als eine option, die ist jetzt verfügbar in node.js und in modernen Browsern oder über transpilers.async/await
ist groß, aber Sie sind im Grunde nur syntaktischer Zucker (großer writeup auf dieser), ermöglicht es Ihnen zu schreiben, auf dem top-level, was sonst am Ende in irgendeiner form.then()
–curlies. In der Tat, es funktioniert, wenn transpiled... immer noch keine Möglichkeit zu warten, in den echten Haupt-thread von, sagen wir, ein Befehlszeilen-nodejs-app zu haben, die Letzte Zeile der Ausgabe auf einem top-Niveau.Wenn mit ES2016 können Sie
async
undawait
und tun Sie etwas wie:Wenn mit ES2015 können Sie Generatoren. Wenn Sie nicht wie die syntax können abstrakte Sie es Weg mit einem
async
utility-Funktion als hier erklärt.Wenn mit ES5 Sie werden wahrscheinlich wollen, eine Bibliothek, wie Bluebird geben Ihnen mehr Kontrolle.
Schließlich, wenn Ihre runtime unterstützt ES2015 bereits die Reihenfolge der Ausführung erhalten werden kann mit der Parallelität mit Holen Injektion.
async
/await
.async
/await
ist nur eine andere syntax fürPromise.then
.async
nicht warten... es sei denn, es Erträge mitawait
. Die ES2016/ES7 Beispiel noch nicht ausgeführt werden kann, SO hier ist etwas code, den ich schrieb vor drei Jahren demonstriert das Verhalten.Andere Möglichkeit ist die Verwendung Versprechen.alle warten, für eine Reihe von Versprechungen zu beheben.
Der Code unten zeigt, wie zu warten, bis alle Versprechen zu lösen, und befasst sich dann mit den Ergebnissen, sobald Sie sind alle bereit, (als, die zu sein schien das Ziel der Frage); Allerdings beginnen konnte, offensichtlich Ausgabe vor der Mitte aufgelöst hat, einfach durch hinzufügen von code, bevor Sie es nennt, zu lösen.
JS:
HTML:
Können Sie es manuell tun. (Ich weiß, dass ist keine gute Lösung, aber..)
verwenden
while
Schleife, bis dieresult
hat nicht einen Wert