Warten ist nur in der asynchronen Funktion gültig


127

Ich habe diesen Code geschrieben lib/helper.js

var myfunction = async function(x,y) {
   ....
   reutrn [variableA, variableB]
}
exports.myfunction = myfunction;

und dann habe ich versucht, es in einer anderen Datei zu verwenden

 var helper = require('./helper.js');   
 var start = function(a,b){
     ....
     const result = await helper.myfunction('test','test');
 }
 exports.start = start;

Ich habe einen Fehler bekommen

"Warten ist nur in der asynchronen Funktion gültig"

Was ist das Problem?


1
Nun, das Problem ist, dass awaitnur innerhalb einer asyncFunktion verwendet werden kann. Das heißt, awaitmacht eine Funktion asynchron, daher muss sie als solche deklariert werden.
Pointy

Was ist der aktuelle Fehler?
acdcjunior

immer noch das gleiche, SyntaxError: Warten ist nur in der asynchronen Funktion gültig
j.doe

Sie müssen mehr Kontext über Ihren Code teilen.
Ele

Antworten:


156

Der Fehler bezieht sich nicht auf, myfunctionsondern auf start.

async function start() {
   ....

   const result = await helper.myfunction('test', 'test');
}

// My function
const myfunction = async function(x, y) {
  return [
    x,
    y,
  ];
}

// Start function
const start = async function(a, b) {
  const result = await myfunction('test', 'test');
  
  console.log(result);
}

// Call start
start();



Ich nutze die Gelegenheit dieser Frage, um Sie über ein bekanntes Anti-Muster zu beraten, awaitdas lautet : return await.


FALSCH

async function myfunction() {
  console.log('Inside of myfunction');
}

// Here we wait for the myfunction to finish
// and then returns a promise that'll be waited for aswell
// It's useless to wait the myfunction to finish before to return
// we can simply returns a promise that will be resolved later

// useless async here
async function start() {
  // useless await here
  return await myfunction();
}

// Call start
(async() => {
  console.log('before start');

  await start();
  
  console.log('after start');
})();


RICHTIG

async function myfunction() {
  console.log('Inside of myfunction');
}

// Here we wait for the myfunction to finish
// and then returns a promise that'll be waited for aswell
// It's useless to wait the myfunction to finish before to return
// we can simply returns a promise that will be resolved later

// Also point that we don't use async keyword on the function because
// we can simply returns the promise returned by myfunction
function start() {
  return myfunction();
}

// Call start
(async() => {
  console.log('before start');

  await start();
  
  console.log('after start');
})();


Beachten Sie auch, dass es einen Sonderfall gibt, in dem dies return awaitrichtig und wichtig ist: (Verwenden von try / catch)

Gibt es Leistungsprobleme mit "Rückkehr warten"?


Aber das funktioniert nicht, ich habe meinen Code aktualisiert. Ich bekomme immer noch den gleichen Fehler
j.doe

@ j.doe Ich habe ein Snippet hinzugefügt
Grégory NEUT

2
Danke, ich habe mein Problem gefunden. Ich habe versucht, es innerhalb eines Rückrufs zu tun, ist die Funktion start (). Die Lösung war: const start = asynchrone Funktion (a, b) {task.get (Optionen, asynchrone Funktion (Fehler, Ergebnis1) {const result = warte auf meine Funktion ('test', 'test');
j.doe

In Anbetracht dessen, dass der Knoten ein einzelner Thread ist. Verringert es nicht die Anforderung pro Minute und erhöht auch die Verzögerung zwischen dem Erfüllen von Anforderungen.
Rishabh Dhiman

1
Es ist erwähnenswert, dass es im Beispiel "RICHTIG" nicht erforderlich ist, startals asyncFunktion zu deklarieren (obwohl einige dies sowieso tun werden, um genauer zu sein)
Gershom

11

Als ich diesen Fehler bekam, stellte sich heraus, dass ich die Kartenfunktion in meiner "asynchronen" Funktion aufgerufen hatte. Diese Fehlermeldung bezog sich also tatsächlich auf die Kartenfunktion, die nicht als "asynchron" markiert war. Ich habe dieses Problem umgangen, indem ich den Aufruf "Warten" aus der Kartenfunktion genommen und eine andere Methode gefunden habe, um das erwartete Verhalten zu erhalten.

var myfunction = async function(x,y) {
    ....
    someArray.map(someVariable => { // <- This was the function giving the error
        return await someFunction(someVariable);
    });
}

2
Das war das Problem für mich. Ich habe die Kartenfunktion durch eine for-Schleife ersetzt, was für mich eine einfache Lösung war. Abhängig von Ihrem Code funktioniert diese Lösung möglicherweise nicht für Sie.
Thomas

5
Zu Ihrer someArray.map(async (someVariable) => { return await someFunction(someVariable)})
Information

1
Das awaitin Ihrem Code ist irreführend, da Array.mapdie Funktion nicht als asynchrone Funktion behandelt wird. Um ganz klar zu sein, stehen nach Abschluss der mapFunktion someFunctionalle aus. Wenn Sie wirklich warten möchten, bis die Funktionen abgeschlossen sind, müssen Sie schreiben: await Promise.all(someArray.map(someVariable => someFunction(someVariable)))oder await Promise.all(someArray.map(someFunction))).
Grégory NEUT

9

Um verwendet zu werden await, muss der ausführende Kontext asyncin der Natur liegen

Wie gesagt, Sie müssen vor allem die Art Ihrer Aufgabe definieren, in der executing contextSie zu awaiteiner Aufgabe bereit sind .

Stellen Sie einfach asyncvor die fnDeklaration, in der Ihre asyncAufgabe ausgeführt wird.

var start = async function(a, b) { 
  // Your async task will execute with await
  await foo()
  console.log('I will execute after foo get either resolved/rejected')
}

Erläuterung:

In Ihrer Frage importieren Sie eine, methoddie asynchronousin der Natur liegt und parallel ausgeführt wird. Wenn Sie jedoch versuchen, diese asyncMethode auszuführen, befindet sich eine andere Methode, execution contextdie Sie für die asyncVerwendung definieren müssen await.

 var helper = require('./helper.js');   
 var start = async function(a,b){
     ....
     const result = await helper.myfunction('test','test');
 }
 exports.start = start;

Ich frage mich, was unter der Haube los ist

awaitverbraucht vielversprechende / zukünftige / aufgabenrückgebende Methoden / Funktionen und asyncmarkiert eine Methode / Funktion als wartungsfähig.

Auch wenn Sie sind vertraut mit promises, awaitist eigentlich den gleichen Prozess der Verheißung / beheben zu tun. Erstellen Sie eine Versprechenskette und führen Sie die nächste Aufgabe im resolveRückruf aus.

Weitere Informationen finden Sie unter MDN DOCS .


Selbst mit Async in der
Startfunktion erhalte

Ich bin nicht sicher, wo Sie fehlen und diesen Fehler erhalten. Es gibt keine so komplexe Erklärung, um diesen Fehler zu beheben.
Satyam Pathak

Dies ist eine richtige Antwort und erklärt tatsächlich den unterstrichenen Grund. gewählt.
Linehrr

3

Die aktuelle Implementierung von async/ awaitunterstützt nur das awaitSchlüsselwort innerhalb von asyncFunktionen. Ändern Sie Ihre startFunktionssignatur, damit Sie sie awaitinnerhalb verwenden können start.

 var start = async function(a, b) {

 }

Für Interessenten befindet sich der Vorschlag für die oberste Ebene awaitderzeit in Phase 2: https://github.com/tc39/proposal-top-level-await


1
Leider bedeutet dies im Grunde, dass Sie ALLE Ihre Funktionen über Ihre gesamte Codebasis hinweg asynchron machen müssen. Wenn Sie await verwenden möchten, müssen Sie dies in einer asynchronen Funktion tun. Dies bedeutet, dass Sie die Antwort dieser Funktion in der aufrufenden Funktion abwarten müssen. Dies bedeutet wiederum, dass ALLE Ihre Funktionen asynchron werden müssen. Für mich bedeutet dies, dass das Warten auf Async nicht einsatzbereit ist. Wenn Sie mit wait eine asynchrone Methode aufrufen können, unabhängig davon, ob die aktuelle Funktion synchron oder asynchron ist, ist sie für die Hauptsendezeit bereit.
Rodney P. Barbati

1
Jede Funktion, die durch eine beliebige Indirektionsebene von den Ergebnissen eines externen Prozesses abhängig ist, muss und sollte definiert werden async- das ist der ganze Punkt von async.
Gershom

Sie können es derzeit in der Knotenreplikation mit der --experimental-repl-awaitOption verwenden.
lodz

3

Ich hatte das gleiche Problem und der folgende Codeblock gab die gleiche Fehlermeldung aus:

repositories.forEach( repo => {
        const commits = await getCommits(repo);
        displayCommit(commits);
});

Das Problem ist, dass die Methode getCommits () asynchron war, aber ich habe ihr das Argument repo übergeben, das auch von einem Promise erzeugt wurde. Also musste ich das Wort async wie folgt hinzufügen: async (repo) und es fing an zu funktionieren:

repositories.forEach( async(repo) => {
        const commits = await getCommits(repo);
        displayCommit(commits);
});

0

async / await ist der Mechanismus für den Umgang mit Versprechen, zwei Möglichkeiten, wie wir dies tun können

functionWhichReturnsPromise()
            .then(result => {
                console.log(result);
            })
            .cathc(err => {
                console.log(result);

            });

oder wir können warten verwenden, um auf das Versprechen zu warten, es zuerst vollständig einzureichen, was bedeutet, dass es entweder abgelehnt oder gelöst wird.

Wenn wir nun await (Warten auf die Erfüllung eines Versprechens) innerhalb einer Funktion verwenden möchten, muss die Containerfunktion eine asynchrone Funktion sein, da wir darauf warten, dass ein Versprechen asynchron erfüllt wird || Sinn machen, oder?.

async function getRecipesAw(){
            const IDs = await getIds; // returns promise
            const recipe = await getRecipe(IDs[2]); // returns promise
            return recipe; // returning a promise
        }

        getRecipesAw().then(result=>{
            console.log(result);
        }).catch(error=>{
            console.log(error);
        });

-2

"Warten ist nur in der asynchronen Funktion gültig"

Aber wieso? 'Warten' verwandelt einen asynchronen Anruf explizit in einen synchronen Anruf, und daher kann der Anrufer nicht asynchron (oder asynchron) sein - zumindest nicht, weil der Anruf bei 'Warten' getätigt wird.


1
Warten wartet eigentlich nicht auf Ergebnisse - es gibt sofort ein Versprechen zurück. Genau das wollte ich vermitteln. Wenn "Warten" tatsächlich gewartet hat und die Kontrolle nicht an den Aufrufer zurückgegeben hat, kann eine Funktion, die ein Schlüsselwort "Warten" enthält, buchstäblich nicht als asynchron markiert werden. Aber stattdessen haben wir jede Funktion, die Warten enthält oder eine Funktion aufruft, die schließlich eine Funktion aufruft, die Warten enthält, muss asynchron sein. Wenn Sie einen Anruf nur einmal abwarten, müssen alle Ihre Funktionen als asynchron markiert sein.
Rodney P. Barbati

-5

Ja, warte / asynchron war ein großartiges Konzept, aber die Implementierung ist völlig kaputt.

Aus irgendeinem Grund wurde das Schlüsselwort await so implementiert, dass es nur innerhalb einer asynchronen Methode verwendet werden kann. Dies ist in der Tat ein Fehler, obwohl Sie ihn nirgendwo anders als hier sehen werden. Die Lösung für diesen Fehler besteht darin, das Schlüsselwort await so zu implementieren, dass es nur zum Aufrufen einer asynchronen Funktion verwendet werden kann, unabhängig davon, ob die aufrufende Funktion selbst synchron oder asynchron ist.

Aufgrund dieses Fehlers müssen ALLE Ihre Funktionen als asynchron markiert sein und ALLE Ihre Funktionsaufrufe warten verwenden, wenn Sie mit wait eine echte asynchrone Funktion irgendwo in Ihrem Code aufrufen.

Dies bedeutet im Wesentlichen, dass Sie den Overhead von Versprechungen zu allen Funktionen in Ihrer gesamten Anwendung hinzufügen müssen, von denen die meisten nicht asynchron sind und niemals asynchron sein werden.

Wenn Sie tatsächlich darüber nachdenken, sollte für die Verwendung von "Warten" in einer Funktion die Funktion erforderlich sein, die das Schlüsselwort "Warten" enthält, um nicht ASYNC zu sein. Dies liegt daran, dass das Schlüsselwort "Warten" die Verarbeitung in der Funktion unterbricht, in der das Schlüsselwort "Warten" gefunden wird. Wenn die Verarbeitung in dieser Funktion angehalten wird, ist sie definitiv NICHT asynchron.

Also, an die Entwickler von Javascript und ECMAScript - bitte korrigieren Sie die Warten / Async-Implementierung wie folgt ...

  • wait kann nur zum Aufrufen von asynchronen Funktionen verwendet werden.
  • Warten kann in jeder Art von Funktion erscheinen, synchron oder asynchron.
  • Ändern Sie die Fehlermeldung von "Warten ist nur in der asynchronen Funktion gültig" in "Warten kann nur zum Aufrufen von asynchronen Funktionen verwendet werden".

Sie können es einen Fehler nennen, wenn Sie möchten, aber ich bin anderer Meinung. Es gibt keinen Code, der "pausiert" - vielmehr gibt es Code, der ohne die Ergebnisse eines externen Prozesses (normalerweise io) nicht abgeschlossen werden kann. Ein solcher Code sollte als "asynchron" bezeichnet werden, da im Gegensatz zur Javascript-VM, die Single-Threaded ist, viele externe Prozesse gleichzeitig (nicht synchron) ausgeführt werden können sollten. Wenn Sie viele Funktionen haben, die überarbeitet werden müssen async, spiegelt dies die Tatsache wider, dass viele Ihrer Funktionen die Ergebnisse externer Prozesse erfordern. Das ist meiner Meinung nach völlig kanonisch.
Gershom

Erwähnenswert ist auch der schreckliche Nachteil der Einschränkung await, dass sie nur für Funktionsaufrufe verwendet werden kann: Für einen einzelnen externen Prozess konnte nur ein einzelner Punkt im Javascript-Code benachrichtigt werden, wenn dieser Prozess abgeschlossen ist. Wenn beispielsweise der Inhalt einer Datei für drei unabhängige Zwecke benötigt wird, muss jeder Zweck unabhängig voneinander ausgeführt werden. let content = await readTheFile();Dies liegt daran, dass das "Versprechen des Inhalts der Datei" nicht erwartet werden kann, sondern nur "das Lesen der Datei und die Wiederaufnahme, sobald sie abgeschlossen ist lesen".
Gershom

Ok, nennen wir es nicht Code, der pausiert, oder Code, der nicht abgeschlossen werden kann, sondern wie wäre es mit blockiertem Warten. Hier ist die Reibung - die Funktion, die beim Warten blockiert ist oder die nicht abgeschlossen werden kann, ist die Funktion, die das Schlüsselwort await enthält. Es ist nicht die asynchrone Funktion, die mit dem Schlüsselwort await aufgerufen wird. Daher sollte die Funktion, die das Schlüsselwort await enthält, definitiv NICHT als asynchron markiert werden müssen - sie ist blockiertes Warten, was das Gegenteil von asynchron ist.
Rodney P. Barbati

Um dies ganz klar zu machen, beachten Sie Folgendes: Mit wait soll die Verwendung asynchroner Funktionen vereinfacht werden, indem sie als synchron erscheinen (dh ich kann die Dinge in einer bestimmten Reihenfolge ausführen). Das Erzwingen, dass die Funktion, die das Warten enthält, asynchron ist, ist eine völlige Fehlbezeichnung. Sie haben das Warten verwendet, damit es synchron wird. Eine Funktion, die ein Warten enthält, ist in jeder erdenklichen Weise absolut keine asynchrone Funktion !!!
Rodney P. Barbati

1
@Gershom - das klingt vernünftig. Vielen Dank!
Rodney P. Barbati
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.