Hatten Sie jemals das Gefühl, in einem Café in der Schlange auf JavaScript zu warten, um Ihren Latte zu holen? Asynchrones Programmieren kann sich oft so anfühlen – die gleichzeitige Verarbeitung mehrerer Aufträge kann dazu führen, dass Sie warten müssen. Glücklicherweise sorgen Tools wie Promises und async/await dafür, dass der Prozess reibungslos und effizient bleibt und Ihr Code ohne Verzögerungen weiterläuft.
In diesem Leitfaden erklären wir, wie Promises funktionieren, warum async/await eingeführt wurde und wie es das Schreiben von asynchronem Code vereinfacht. Egal, ob Sie ein Anfänger sind, der versucht, diese Konzepte zu verstehen, oder ob Sie Klarheit darüber suchen, wann die einzelnen Ansätze anzuwenden sind, dieser Artikel wird Ihnen helfen, die Grundlagen zu beherrschen.
Promises sind ein grundlegendes Konzept in JavaScript für die Handhabung asynchroner Vorgänge. Im Kern stellt ein Versprechen einen Wert dar, der jetzt, später oder nie verfügbar sein kann. Stellen Sie sich das wie eine Sendungsverfolgungsnummer für ein Paket vor: Auch wenn Sie das Paket noch nicht haben, gibt Ihnen die Sendungsverfolgungsnummer die Gewissheit, dass es unterwegs ist (oder informiert Sie, wenn etwas schief gelaufen ist).
Aufbauend auf der „Jetzt, später oder nie“-Erzählung funktioniert ein Versprechen tatsächlich in einem von drei Zuständen:
Das Erstellen und Arbeiten mit Promises erfordert eine einfache API. So können Sie ein Versprechen definieren:
const fetchData = new Promise((resolve, reject) => { setTimeout(() => { const data = { id: 1, name: "JavaScript Basics" }; resolve(data); // Simulates a successful operation // reject("Error: Unable to fetch data"); // Simulates a failure }, 1000); });
Um das Ergebnis zu verarbeiten, können Sie die Methoden .then(), .catch() und .finally() mit dem Promise-Objekt verketten:
fetchData .then((data) => { console.log("Data received:", data); }) .catch((error) => { console.error(error); }) .finally(() => { console.log("Operation complete."); });
Der Rückruf in der then()-Methode wird ausgeführt, wenn das Promise mit einem erfolgreichen Ergebnis aufgelöst wird. Der Rückruf in der Methode .catch() wird ausgeführt, wenn das Promise mit einem fehlgeschlagenen Ergebnis aufgelöst wird, und der Rückruf in der Methode „final()“ wird ausgeführt, nachdem das Promise aufgelöst wurde, unabhängig vom Ergebnis der Auflösung.
Versprechen bieten eine sauberere Alternative zu tief verschachtelten Rückrufen, die oft als „Rückrufhölle“ bezeichnet werden. Anstatt Rückrufe zu stapeln, ermöglichen Promises die Verkettung, wodurch der Ablauf von Vorgängen einfacher zu verfolgen ist:
doTask1() .then((result1) => doTask2(result1)) .then((result2) => doTask3(result2)) .catch((error) => console.error("An error occurred:", error));
So hätte derselbe Code ausgesehen, wenn er mit herkömmlichen Rückrufen geschrieben worden wäre:
doTask1((error1, result1) => { if (error1) { console.error("An error occurred:", error1); return; } doTask2(result1, (error2, result2) => { if (error2) { console.error("An error occurred:", error2); return; } doTask3(result2, (error3, result3) => { if (error3) { console.error("An error occurred:", error3); return; } console.log("Final result:", result3); }); }); });
Verwirrend, nicht wahr? Aus diesem Grund haben Promises bei ihrer Einführung die JavaScript-Codierungsstandards grundlegend verändert.
Obwohl Promises die herkömmlichen Rückruffunktionen deutlich verbessert hat, waren sie nicht ohne ihre eigenen, einzigartigen Herausforderungen. Trotz ihrer Vorteile können sie in komplexen Szenarien unhandlich werden, was zu ausführlichem Code und Debugging-Schwierigkeiten führt.
Auch bei der .then()-Verkettung können Promises zu unübersichtlichem Code führen, wenn mehrere asynchrone Vorgänge verarbeitet werden. Beispielsweise kann sich die Verwaltung sequenzieller Vorgänge mit .then()-Blöcken und die Fehlerbehandlung mit .catch() eintönig anfühlen und schwieriger zu befolgen sein.
const fetchData = new Promise((resolve, reject) => { setTimeout(() => { const data = { id: 1, name: "JavaScript Basics" }; resolve(data); // Simulates a successful operation // reject("Error: Unable to fetch data"); // Simulates a failure }, 1000); });
Die Verkettungssyntax ist zwar sauberer als verschachtelte Rückrufe, aber dennoch ausführlich, insbesondere wenn eine detaillierte benutzerdefinierte Fehlerbehandlungslogik erforderlich ist. Darüber hinaus kann das Vergessen, am Ende einer Kette ein .catch() hinzuzufügen, zu stillen Fehlern führen, was das Debuggen schwierig macht.
Außerdem sind Stack-Traces in Promises nicht so intuitiv wie die in synchronem Code. Wenn ein Fehler auftritt, zeigt der Stack-Trace möglicherweise nicht eindeutig an, wo das Problem in Ihrem asynchronen Fluss entstanden ist.
Obwohl Versprechen dazu beitragen, die Rückrufhölle zu reduzieren, können sie dennoch zu Komplexität führen, wenn Aufgaben voneinander abhängig sind. Verschachtelte .then()-Blöcke können sich für bestimmte Anwendungsfälle wieder einschleichen und einige der Lesbarkeitsprobleme mit sich bringen, die sie lösen sollten.
Die asynchrone Programmierung in JavaScript hat mit der Einführung von async/await in ES2017 (ES8) einen großen Sprung nach vorne gemacht. Async/await basiert auf Promises und ermöglicht es Entwicklern, asynchronen Code zu schreiben, der eher wie synchroner Code aussieht und sich so verhält. Dies macht es zu einem echten Game-Changer, da es die Lesbarkeit verbessert, die Fehlerbehandlung vereinfacht und die Ausführlichkeit reduziert.
Async/await ist eine Syntax, die das Verständnis und die Wartung von asynchronem Code erleichtern soll.
Das Schlüsselwort async wird verwendet, um eine Funktion zu deklarieren, die immer ein Promise zurückgibt. Innerhalb dieser Funktion pausiert das Schlüsselwort „await“ die Ausführung, bis ein Promise aufgelöst oder abgelehnt wird. Dies führt zu einem Ablauf, der sich selbst bei komplexen asynchronen Vorgängen linear und intuitiv anfühlt.
Hier ist ein Beispiel dafür, wie async/await dasselbe Codebeispiel vereinfacht, das Sie oben gesehen haben:
fetchData .then((data) => { console.log("Data received:", data); }) .catch((error) => { console.error(error); }) .finally(() => { console.log("Operation complete."); });
Async/await macht .then()-Ketten überflüssig und ermöglicht den sequenziellen Fluss des Codes. Dies erleichtert das Verfolgen der Logik, insbesondere bei Aufgaben, die nacheinander ausgeführt werden müssen.
Bei Promises müssen Fehler auf jeder Ebene der Kette mit .catch() abgefangen werden. Async/await hingegen konsolidiert die Fehlerbehandlung mithilfe von Try/Catch, reduziert Wiederholungen und verbessert die Klarheit.
Async/await erzeugt intuitivere Stack-Traces als Promises. Wenn ein Fehler auftritt, spiegelt die Ablaufverfolgung die tatsächliche Funktionsaufrufhierarchie wider, sodass das Debuggen weniger frustrierend ist. Im Großen und Ganzen fühlt sich async/await „natürlicher“ an, da es sich an der Art und Weise orientiert, wie synchroner Code geschrieben wird.
Wie Sie bereits gesehen haben, glänzt Async/await in puncto Lesbarkeit, insbesondere bei sequentiellen Vorgängen. Versprechen können mit ihrer .then()- und .catch()-Verkettung schnell ausführlich oder komplex werden. Im Gegensatz dazu ist Async/Await-Code einfacher zu befolgen, da er eine synchrone Struktur nachahmt.
Versprechen haben immer noch ihre Berechtigung, insbesondere für gleichzeitige Aufgaben. Methoden wie Promise.all() und Promise.race() sind effizienter für die parallele Ausführung mehrerer asynchroner Vorgänge. Async/await kann solche Fälle ebenfalls verarbeiten, erfordert jedoch zusätzliche Logik, um das gleiche Ergebnis zu erzielen.
const fetchData = new Promise((resolve, reject) => { setTimeout(() => { const data = { id: 1, name: "JavaScript Basics" }; resolve(data); // Simulates a successful operation // reject("Error: Unable to fetch data"); // Simulates a failure }, 1000); });
Während die zentralisierte Fehlerbehandlung mit einem einzigen .catch() für lineare Promises-Ketten gut funktioniert, wird für eine optimale Lesbarkeit empfohlen, verteilte .catch-Aufrufe für verschiedene Fehlertypen über Ketten hinweg zu verwenden.
Andererseits bietet ein Try/Catch-Block eine natürlichere Struktur für den Umgang mit Fehlern, insbesondere bei der Bearbeitung sequenzieller Aufgaben.
In Bezug auf die Leistung entspricht async/await im Wesentlichen Promises, da es darauf aufbaut. Für Aufgaben, die Parallelität erfordern, kann Promise.all() jedoch effizienter sein, da es die parallele Ausführung mehrerer Versprechen ermöglicht und schnell fehlschlägt, wenn ein Versprechen abgelehnt wird.
Wenn Ihre Aufgaben viele gleichzeitige Vorgänge umfassen, wie z. B. das gleichzeitige Abrufen von Daten von mehreren APIs, sind Promises höchstwahrscheinlich die bessere Wahl. Wenn Ihr asynchroner Code nicht viel Verkettung erfordert, wäre Promises aufgrund seiner Einfachheit auch in dieser Situation gut geeignet.
Andererseits eignet sich async/await hervorragend für Situationen, in denen viele Aufgaben nacheinander ausgeführt werden müssen oder wenn Lesbarkeit und Wartbarkeit Priorität haben. Wenn Sie beispielsweise eine Reihe abhängiger Vorgänge haben, wie etwa das Abrufen, Transformieren und Speichern von Daten, bietet async/await eine saubere und synchrone Struktur. Dies erleichtert die Verfolgung des Betriebsablaufs und vereinfacht die zentrale Fehlerbehandlung mit Try/Catch-Blöcken. Async/await ist besonders nützlich für Anfänger oder Teams, die lesbaren Code priorisieren.
JavaScript bietet zwei leistungsstarke Tools zum Verwalten asynchroner Vorgänge: Promises und async/await. Promises revolutionierte die Art und Weise, wie Entwickler mit asynchronen Aufgaben umgehen, löste Probleme wie die Callback-Hölle und ermöglichte die Verkettung. Async/await baut auf Promises auf und bietet eine sauberere Syntax, die sich natürlicher und intuitiver anfühlt, insbesondere bei sequentiellen Aufgaben.
Da Sie nun beide Ansätze erkundet haben, sind Sie in der Lage, den besten für Ihre Bedürfnisse auszuwählen. Versuchen Sie, eine Promise-basierte Funktion in async/await zu konvertieren, und beobachten Sie den Unterschied in der Lesbarkeit!
Weitere Informationen finden Sie in der MDN Promise-Dokumentation oder experimentieren Sie mit einer interaktiven Coding-Sandbox!
Das obige ist der detaillierte Inhalt vonAsync/Await vs Promises: Eine einfache Anleitung für JavaScript-Anfänger. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!