Warten auf das Ende einer Funktion in JavaScript

Moataz Farid 12 Oktober 2023
  1. sync und async in JavaScript
  2. Verwenden Sie callback, um in JavaScript auf die Beendigung einer Funktion zu warten
  3. Verwenden Sie promises, um in JavaScript auf die Beendigung einer Funktion zu warten
  4. Verwenden Sie async/await, um auf das Ende einer Funktion zu warten, bevor Sie die Ausführung fortsetzen
Warten auf das Ende einer Funktion in JavaScript

Dieses Tutorial führt in JavaScript Callbacks, Promises und async/await ein und zeigt Ihnen, wie Sie auf die Beendigung einer Async-Funktion warten, bevor Sie die Ausführung fortsetzen.

Um zu verstehen, was Promises und async/await sind, müssen wir zunächst verstehen, was die Funktionen aync und async in JavaScript sind.

sync und async in JavaScript

Bei der synchronen Programmierung wird jeweils ein Befehl ausgeführt. Wenn wir eine Funktion aufrufen, die eine lang laufende Aktion ausführt, stoppt sie das Programm, bis es beendet ist.

JavaScript ist traditionell Single-Threaded, auch mit mehreren Kernen. Wir können es dazu bringen, Aufgaben nur in einem einzigen Thread, dem so genannten Hauptthread, auszuführen.

Dieses synchrone Verhalten ist ein limitierender Faktor in den Multi-Threads, hilft aber dem Benutzer beim Schreiben von Codes, ohne sich um Gleichzeitigkeitsprobleme sorgen zu müssen.

Bei der asynchronen Programmierung wird die lang laufende Aktion in einem anderen Thread als dem Hauptthread ausgeführt, so dass die Hauptausführung nicht blockiert wird. Wenn diese lang laufende Funktion beendet ist, wird das Hauptprogramm informiert und erhält Zugriff auf die Ergebnisse.

Die meisten E/A-Primitive in JavaScript sind nicht blockierend. Netzwerkanfragen und Dateisystemoperationen sind alles nichtblockierende Operationen. Das Blockieren ist die Ausnahme in JavaScript.

Da JavaScript auf asynchronen Programmiertechniken basiert, gibt es mehrere Ansätze wie callbacks, promises und async/await, die es Ihnen ermöglichen, Ihre Funktionsausführungen in eine Reihenfolge zu bringen. So dass ein Code-Block oder eine Funktion nicht ausgeführt wird, bevor eine andere spezifische Funktion beendet ist.

sync und async

Die obige Abbildung zeigt den deutlichen Unterschied zwischen asynchroner und synchroner Ausführung von zwei Funktionen.

Verwenden Sie callback, um in JavaScript auf die Beendigung einer Funktion zu warten

Wenn wir synchrone Erklärungen haben, dann ist es einfach, diese Erklärungen nacheinander auszuführen.

function one() {
  console.log('I am function One');
}
function Two() {
  console.log('I am function Two');
}

one();
Two();

Ausgabe:

I am function One 
I am function Two

Nehmen wir an, wir wollen zwei Funktionen ausführen, functionOne() und functionTwo(), so dass functionOne() nach der Ausführung einiger asynchroner Anweisungen innerhalb von functionTwo() ausgeführt werden soll.

function functionOne(_callback) {
  // do some asynchronus work
  _callback();
}

function functionTwo() {
  // do some asynchronus work
  functionOne(() => {
    console.log('I am a callback');
  });
}

functionTwo();

Wenn der obige Code ausgeführt wird, ist das letzte, was auf der Konsole ausgegeben wird, I am a callback. Das berühmte callback-Beispiel ist die Funktion setTimeout mit einer Handler-Funktion, die nach dem Timeout ausgeführt werden soll.

function testCallBack() {
  console.log('log before use setTimeout function');
  setTimeout(() => {
    console.log('inside timeout');
  }, 5000);
  console.log('log after use setTimeout function');
}

testCallBack();

Ausgabe:

log before use setTimeout function
log after use setTimeout function
inside timeout

Verwenden Sie promises, um in JavaScript auf die Beendigung einer Funktion zu warten

Ein “promises” ist ein Objekt, das die schließliche Erfüllung oder das Scheitern einer asynchronen Operation darstellt. Wir hängen den Erfüllungsrückruf an die promises mit einer oder mehreren then-Anweisungen an, und wann kann der Fehlerbehandlungsrückruf im catch aufgerufen werden.

doFirstThing()
    .then(result => doSecondThing(result))
    .then(newResult => doThirdThing(newResult))
    .then(finalResult => {
      console.log('The final result thing' + finalResult);
    })
    .catch(failureCallbackfunction);
}

Die Verkettung von then- und catch-Anweisungen wie im obigen Beispiel ist einer der Vorteile des Versprechens. Wir versprechen doSecondThing(result), sobald das doFirstThing() erfüllt ist. Die Argumente für das then sind optional, aber erforderlich, wenn Sie ein Ergebnis zurückgeben müssen.

Falls ein Fehler auftritt, wird der Browser am Ende der Kette nach dem catch suchen und ihn ausführen. Es ist dem berühmten try-catch sehr ähnlich.

Das folgende Beispiel hilft uns, die promise-Ketten zu verstehen und zeigt uns, wie wir darauf warten können, dass eine Funktion mit asynchronem Verhalten die Ausführung beendet, bevor wir mit der Ausführung fortfahren können.

var resolvedFlag = true;

let mypromise = function functionOne(testInput) {
  console.log('Entered function');
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('Inside the promise');
      if (resolvedFlag == true) {
        resolve('Resolved');
      } else {
        reject('Rejected')
      }
    }, 2000);
  });
};

mypromise()
    .then((res) => {console.log(`The function recieved with value ${res}`)})
    .catch((error) => {
      console.log(`Handling error as we received ${error}`);
    });

Ausgabe:

Entered function
Inside the promise
The function received with value Resolved

Das Erstellen eines Versprechens kann so einfach sein wie die Rückgabe eines neuen Promise(). Der Promise()-Konstruktor erhält eine Funktion als Argument, die zwei Parameter haben sollte - resolve und reject.

Wenn unser Ereignis erfüllt ist und wir das Ergebnis zurückgeben müssen, verwenden wir die Funktion resolve(), wenn wir mit dem, was wir getan haben, erfolgreich waren. Wenn aber ein Fehler auftritt und behandelt werden muss, verwenden wir reject(), um den Fehler an den catch zu senden.

Wir setzen das Flag resolvedFlag = true, um die Fehlerbehandlung im catch zu simulieren. Wenn resolvedFlag auf false gesetzt ist, wird die Funktion reject() aufgerufen, und der Fehler wird im catch-Block behandelt.

Ausgabe:

Entered function
Inside the promise
Handling error as we received Rejected

Verwenden Sie async/await, um auf das Ende einer Funktion zu warten, bevor Sie die Ausführung fortsetzen

Eine andere Möglichkeit, auf die Ausführung einer Funktion zu warten, bevor die Ausführung in der asynchronen Umgebung in JavaScript fortgesetzt wird, ist die Verwendung von async/wait.

Die async-Funktion ist die Funktion, die durch das async-Schlüsselwort deklariert wird, während nur das await-Schlüsselwort innerhalb der async-Funktion erlaubt ist und verwendet wird, um den Fortschritt innerhalb der async-Funktion auszusetzen, bis die Promise-basierte asynchrone Operation erfüllt oder zurückgewiesen wird.

Die Schlüsselwörter async und await ermöglichen asynchrones, auf Versprechen basierendes Verhalten in einem saubereren Stil.

Lassen Sie uns verstehen, wie async/await funktioniert. Die Funktion, auf die wir warten, sollte eine Instanz der Promise-Klasse zurückgeben, um mit dem await-Schlüsselwort auf ihre Ausführung zu warten, bevor sie aufgerufen wird. Wie oben erwähnt, muss die Funktion, die die Anweisung await enthält, mit der Anweisung async deklariert werden.

Das folgende Beispiel zeigt, wie man auf die Beendigung dieser Promise-basierten Funktion wartet, bevor man die Ausführung fortsetzt.

function testAsync() {
  return new Promise((resolve, reject) => {
    // here our function should be implemented
    setTimeout(() => {
      console.log('Hello from inside the testAsync function');
      resolve();
      ;
    }, 5000);
  });
}

async function callerFun() {
  console.log('Caller');
  await testAsync();
  console.log('After waiting');
}

callerFun();

Ausgabe:

Caller
Hello from inside the testAsync function
After waiting

Verwandter Artikel - JavaScript Promises