Asynchroner Code in JavaScript kann Kopfschmerzen bereiten, besonders wenn man gerade erst anfängt, damit zu arbeiten. Moderne Browser und serverseitige Umgebungen wie Node.js nutzen aktiv Asynchronität, um die Ausführung des Codes nicht zu blockieren, während sie auf eine Antwort vom Server, das Lesen einer Datei oder die Ausführung einer Datenbankabfrage warten.
Callbacks und ihre Probleme
Früher wurde Asynchronität in JavaScript durch Callbacks (Callback-Funktionen) realisiert. Dies sind Funktionen, die als Argumente übergeben werden und nach Abschluss einer asynchronen Operation aufgerufen werden.
function fetchData(callback) {
setTimeout(() => {
callback("Daten erhalten!");
}, 1000);
}
fetchData((message) => {
console.log(message);
});
Dieser Ansatz funktioniert, aber bei zunehmender Komplexität kann er sich in die sogenannte "Callback-Hölle" verwandeln:
function step1(callback) {
setTimeout(() => {
console.log("Schritt 1");
callback();
}, 1000);
}
function step2(callback) {
setTimeout(() => {
console.log("Schritt 2");
callback();
}, 1000);
}
function step3(callback) {
setTimeout(() => {
console.log("Schritt 3");
callback();
}, 1000);
}
step1(() => {
step2(() => {
step3(() => {
console.log("Fertig!");
});
});
});
Dieser Code ist schwer zu lesen, zu warten und zu erweitern. Daher wurde Promise eingeführt.
Promises: eine neue Ebene der Asynchronität
Das Objekt Promise ermöglicht es, mit asynchronen Operationen in einer strukturierteren Weise zu arbeiten.
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Daten erhalten!");
}, 1000);
});
}
fetchData().then((message) => {
console.log(message);
});