Async/Await – Asynchrone Programmierung leicht gemacht
Asynchrone Programmierung ist ein wesentlicher Bestandteil moderner JavaScript-Entwicklung, insbesondere bei der Arbeit mit Netzwerkanfragen, Dateisystemen oder anderen Operationen, die Zeit in Anspruch nehmen. Mit der Einführung von Async/Await in ES2017 wurde der Umgang mit asynchronem Code erheblich vereinfacht. In diesem Artikel werde ich erklären, wie Async/Await funktioniert und wie es deinen Code lesbarer und wartbarer macht.
Was ist Async/Await?
Async/Await ist eine Syntax-Erweiterung für Promises, die es ermöglicht, asynchronen Code so zu schreiben, als wäre er synchron. Es basiert auf der Verwendung der Schlüsselwörter async
und await
, um die Ausführung von asynchronen Funktionen zu steuern.
async
deklariert eine Funktion als asynchron und stellt sicher, dass die Funktion immer ein Promise zurückgibt.await
pausiert die Ausführung innerhalb einerasync
-Funktion, bis ein Promise aufgelöst wird.
Warum Async/Await verwenden?
Vor Async/Await wurde asynchroner Code hauptsächlich mit Callbacks oder Promises gehandhabt. Während Promises bereits eine Verbesserung gegenüber verschachtelten Callbacks (Callback Hell) darstellen, können sie bei komplexen Sequenzen von asynchronen Operationen dennoch unübersichtlich werden. Async/Await ermöglicht es, diesen Code zu vereinfachen und lesbarer zu gestalten.
Grundlagen der Verwendung
Eine asynchrone Funktion definieren:
async function fetchData() {
// Funktion enthält asynchronen Code
}
Das await
Schlüsselwort verwenden:
async function fetchData() {
const response = await fetch('https://swapi.dev/api/people/1/');
const data = await response.json();
console.log(data);
}
In diesem Beispiel:
- Die Funktion
fetchData
ist mitasync
deklariert. await
wird verwendet, um auf die Auflösung der Promises vonfetch
undresponse.json()
zu warten.- Der Code nach dem
await
wird erst ausgeführt, wenn das Promise erfüllt ist.
Ein einfaches Beispiel
Vergleichen wir den Code mit Promises und mit Async/Await.
Mit Promises:
function fetchUser() {
return fetch('https://swapi.dev/api/people/1/')
.then(response => response.json())
.then(person => {
console.log(person);
})
.catch(error => {
console.error('Fehler:', error);
});
}
fetchUser();
Mit Async/Await:
async function fetchUser() {
try {
const response = await fetch('https://swapi.dev/api/people/1/');
const person = await response.json();
console.log(person);
} catch (error) {
console.error('Fehler:', error);
}
}
fetchUser();
Der Async/Await-Code ist linear und sieht ähnlich wie synchroner Code aus, was das Verständnis erleichtert.
Fehlerbehandlung mit try...catch
Da await
die Ausführung der Funktion pausiert, können wir normale try...catch
-Blöcke verwenden, um Fehler zu behandeln.
async function fetchData() {
try {
const response = await fetch('https://swapi.dev/api/people/1/');
if (!response.ok) {
throw new Error(`HTTP-Fehler! Status: ${response.status}`);
}
const { name } = await response.json();
console.log(name);
} catch (error) {
console.error('Fehler:', error);
}
}
Parallelisierung von asynchronen Operationen
Wenn du mehrere asynchrone Operationen hast, die unabhängig voneinander sind, kannst du sie parallel ausführen, um die Gesamtzeit zu verkürzen.
Sequentielle Ausführung (langsamer):
async function getData() {
const data1 = await fetchData1();
const data2 = await fetchData2();
return [data1, data2];
}
Parallele Ausführung (schneller):
async function getData() {
const promise1 = fetchData1();
const promise2 = fetchData2();
const data1 = await promise1;
const data2 = await promise2;
return [data1, data2];
}
Oder noch besser mit Promise.all
:
async function getData() {
const [data1, data2] = await Promise.all([fetchData1(), fetchData2()]);
return [data1, data2];
}
Wichtige Hinweise
-
Nur innerhalb von
async
-Funktionen: Dasawait
Schlüsselwort kann nur innerhalb von Funktionen verwendet werden, die mitasync
deklariert sind.// Falsch (nach ES2017) const data = await fetchData(); // SyntaxError // Richtig async function getData() { const data = await fetchData(); }
-
Verwendung von
await
außerhalb und innerhalb vonasync
-Funktionen: Mit der Einführung von Top-Levelawait
im ECMAScript 2022-Standard kann dasawait
-Schlüsselwort nun auch außerhalb von Funktionen verwendet werden, die mitasync
deklariert sind, solange es in einem ES-Modul geschieht.// Richtig in ES-Modulen (ab ECMAScript 2022) const data = await fetchData(); // Immer noch richtig async function getData() { const data = await fetchData(); }
-
async
Funktionen geben immer ein Promise zurück: Auch wenn du kein Promise explizit zurückgibst, wird die Rückgabe in ein Promise verpackt.async function add(a, b) { return a + b; } add(2, 3).then(result => console.log(result)); // 5
-
Fehler propagieren automatisch: Wenn innerhalb einer
async
-Funktion ein Fehler auftritt und nicht abgefangen wird, wird das zurückgegebene Promise abgelehnt.
Anwendungsbeispiel: Daten von einer API abrufen
async function getPerson(id) {
try {
const response = await fetch(`https://swapi.dev/api/people/${id}/`);
if (!response.ok) {
throw new Error(`Person nicht gefunden: ${id}`);
}
const { name, birth_year} = await response.json();
console.log(`${name}: ${birth_year}`);
} catch (error) {
console.error('Fehler:', error.message);
}
}
getPerson(1);
Async/Await mit Arrow Functions
Async/Await kann auch mit Pfeilfunktionen verwendet werden:
const fetchData = async () => {
const data = await getData();
console.log(data);
};
Fazit
Async/Await revolutioniert die Art und Weise, wie wir asynchronen Code in JavaScript schreiben. Es ermöglicht uns, asynchrone Abläufe in einer synchronen Syntax zu schreiben, was den Code einfacher zu lesen und zu warten macht. Durch die Kombination von Async/Await mit anderen modernen JavaScript-Features kannst du effizientere und sauberere Anwendungen entwickeln.
Probiere Async/Await in deinem nächsten Projekt aus und erlebe den Unterschied in der Codequalität und Lesbarkeit!