Ich habe versucht, zwei asynchrone Funktionen miteinander zu verketten, da die erste einen bedingten Rückgabeparameter hatte, der dazu führte, dass die zweite entweder ausgeführt wurde oder das Modul verließ. Ich habe jedoch ein merkwürdiges Verhalten gefunden, das ich in den Spezifikationen nicht finden kann.
async function isInLobby() {
//promise.all([chained methods here])
let exit = false;
if (someCondition) exit = true;
}
Dies ist ein bastardisierter Ausschnitt meines Codes (Sie können den vollen Umfang hier sehen ), der einfach prüft, ob sich ein Spieler bereits in einer Lobby befindet, aber das ist irrelevant.
Als nächstes haben wir diese asynchrone Funktion.
async function countPlayer() {
const keyLength = await scardAsync(game);
return keyLength;
}
Diese Funktion muss nicht ausgeführt werden, wenn exit === true
.
Ich habe es versucht
const inLobby = await isInLobby();
Ich hoffte, dass dies auf Ergebnisse warten würde, damit ich inLobby
es bedingt ausführen kann countPlayer
, erhielt jedoch einen Typfehler ohne spezifische Details.
Warum können Sie await
keine async
Funktion außerhalb des Funktionsumfangs ausführen? Ich weiß, dass es ein Zuckerversprechen ist, also muss es angekettet werden, then
aber warum countPlayer
kann ich auf ein anderes Versprechen warten, aber draußen kann ich nicht await
isInLobby
?
quelle
await isInLobby()
haben und wieinLobby
es verwendet wird? Auch wo / wiecountPlayer
heißt das?isInLobby().then( … countPlayer().then …
Teil beziehen , ist die Lösung trivial: Machen Sie einfach die Funktion, in der diese Aufrufe enthalten sind (die(req, res) =>
eine)async
.await
für Ihren Code? Deshalb habe ich mich gefragt, ob Sie die Antwort akzeptiert haben, die sich nicht wirklich auf das Problem in der Frage bezieht.Antworten:
Die oberste Ebene
await
wird nicht unterstützt. Es gibt einige Diskussionen des Normungsausschusses darüber, warum dies so ist, wie zum Beispiel diese Github-Ausgabe .Es gibt auch einen Gedanken auf Github darüber, warum das Warten auf höchster Ebene eine schlechte Idee ist. Insbesondere schlägt er vor, dass, wenn Sie Code wie diesen haben:
// data.js const data = await fetch( '/data.json' ); export default data;
Jetzt wird jede importierte Datei
data.js
erst ausgeführt, wenn der Abruf abgeschlossen ist, sodass das Laden Ihres Moduls jetzt blockiert ist. Dies macht es sehr schwierig, über die Reihenfolge der App-Module nachzudenken, da wir es gewohnt sind, Javascript auf höchster Ebene synchron und vorhersehbar auszuführen. Wenn dies zulässig wäre, wird es schwierig zu wissen, wann eine Funktion definiert wird.Meiner Ansicht nach ist es eine schlechte Praxis für Ihr Modul, Nebenwirkungen zu haben, indem Sie es einfach laden. Das bedeutet, dass jeder Verbraucher Ihres Moduls Nebenwirkungen erhält, indem er einfach Ihr Modul benötigt. Dies schränkt die Verwendungsmöglichkeiten Ihres Moduls stark ein. Eine oberste Ebene
await
bedeutet wahrscheinlich, dass Sie beim Laden von einer API lesen oder einen Dienst aufrufen . Stattdessen sollten Sie nur asynchrone Funktionen exportieren, die Verbraucher in ihrem eigenen Tempo verwenden können.quelle
void async function() { const inLobby = await isInLobby() }()
inLobby
der Funktion nicht dazu führen, dass sie nicht zugänglich ist?.then()
(sorry, hätte das etwas klarer machen sollen).Das gibt es natürlich immer:
(async () => { await ... // all of the script.... })(); // nothing else
Dies macht eine schnelle Funktion mit Async, wo Sie warten verwenden können. Es erspart Ihnen die Notwendigkeit, eine asynchrone Funktion zu erstellen, die großartig ist! // Credits Silve2611
quelle
await
diese anonyme Funktion benötigen , die wiederum außerhalb von Funktionen nicht funktioniert.Noch besser ist es, ein zusätzliches Semikolon vor den Codeblock zu setzen
;(async () => { await ... })();
Dies verhindert, dass der automatische Formatierer (z. B. in vscode) den ersten Parenthese an das Ende der vorherigen Zeile verschiebt.
Das Problem kann am folgenden Beispiel demonstriert werden:
const add = x => y => x+y const increment = add(1) (async () => { await ... })();
Ohne das Semikolon wird dies wie folgt neu formatiert:
const add = x => y => x+y const increment = add(1)(async () => { await Promise(1) })()
Das ist offensichtlich falsch, weil es die asynchrone Funktion als
y
Parameter zuweist und versucht, eine Funktion aus dem Ergebnis aufzurufen (was eigentlich eine seltsame Zeichenfolge ist'1async () => {...}'
).quelle
add(1);
und nicht vor der asynchronen Funktion ein Semikolon hinzuzufügen .Ab Node.js 14.3.0 wird das Warten auf oberster Ebene unterstützt.
Erforderliche Flagge :
--experimental-top-level-await
.Weitere Details: https://v8.dev/features/top-level-await
quelle
Sie können auf oberster Ebene warten, da Typoskript 3.8
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#-top-level-await
Aus dem Beitrag:
Dies liegt daran, dass zuvor in Das Warten auf JavaScript (zusammen mit den meisten anderen Sprachen mit einer ähnlichen Funktion) war nur im Hauptteil einer asynchronen Funktion zulässig. Mit Warten auf oberster Ebene können wir jedoch Warten auf oberster Ebene eines Moduls verwenden.
const response = await fetch("..."); const greeting = await response.text(); console.log(greeting); // Make sure we're a module export {};
Beachten Sie, dass es eine Subtilität gibt: Das Warten auf oberster Ebene funktioniert nur auf der obersten Ebene eines Moduls, und Dateien werden nur dann als Module betrachtet, wenn TypeScript einen Import oder Export findet. In einigen grundlegenden Fällen müssen Sie möglicherweise export {} als Boilerplate ausschreiben, um dies sicherzustellen.
Das Warten auf oberster Ebene funktioniert möglicherweise nicht in allen Umgebungen, in denen Sie dies zu diesem Zeitpunkt erwarten. Derzeit können Sie das Warten auf oberster Ebene nur verwenden, wenn die Ziel-Compiler-Option es2017 oder höher ist und das Modul esnext oder system ist. Die Unterstützung in mehreren Umgebungen und Bundlern ist möglicherweise eingeschränkt oder erfordert möglicherweise die Aktivierung der experimentellen Unterstützung.
quelle