Heim >Web-Frontend >js-Tutorial >Alles, was Sie über JavaScript-Versprechen und deren Funktionsweise wissen müssen

Alles, was Sie über JavaScript-Versprechen und deren Funktionsweise wissen müssen

Patricia Arquette
Patricia ArquetteOriginal
2024-12-17 03:33:25723Durchsuche

Everything You Need to Know About JavaScript Promises and How They Work

Moderne Webentwicklung ist stark auf asynchrone Aktivitäten angewiesen, um reaktionsfähige, interaktive Anwendungen zu ermöglichen. Unabhängig davon, ob es um das Abrufen von Daten von einer API, das Lesen von Dateien oder das Ausführen von Timern geht, müssen diese Prozesse im Hintergrund ausgeführt werden, ohne dass die Schnittstelle einfriert. JavaScript bietet Ihnen eine zuverlässige Möglichkeit, diese Aufgaben zu erledigen. Dieser Artikel behandelt alles, was Sie über Versprechen wissen müssen, einschließlich grundlegender Ideen und erweiterter Funktionen, um fehlerfreie asynchrone Programme zu entwickeln.

In diesem Artikel erfahren Sie mehr über —

  • Was ist ein Versprechen?

  • Warum Versprechen verwenden?

  • Wie funktionieren Versprechen?

  • Umgang mit Versprechen

  • Versprechen verketten

  • Fehlerbehandlung in Versprechen

  • Erweiterte Promise-Funktionen

  • JavaScript-Ausführungsablauf mit Versprechen (wichtig)

  • Promise-Ketten in Async/Await konvertieren

  • Best Practices und häufige Fehler

Was ist ein Versprechen?

Ein Versprechen in JavaScript ist gleichbedeutend mit einem „Versprechen“, etwas in der Zukunft zu tun. Wenn Sie ein Versprechen geben, sagen Sie: „Ich verspreche, Ihnen die Ergebnisse später mitzuteilen.“ Dieses Ergebnis kann Erfolg oder Misserfolg sein.

Mit anderen Worten, ein Versprechen ist ein Objekt, das den endgültigen Erfolg (oder Misserfolg) einer asynchronen Operation und den daraus resultierenden Wert widerspiegelt. Damit können Sie Handler mit dem Erfolg oder Misserfolg einer asynchronen Aktion korrelieren, wodurch Ihr Code leichter lesbar und wartbar wird.

Warum Versprechen verwenden?

In JavaScript beispielsweise wurden zeitaufwändige Vorgänge – wie das Abrufen von Daten von einem Server – im Allgemeinen mit Rückrufen durchgeführt. Ein Rückruf ist einfach eine Funktion, die an eine andere Funktion übergeben wird, um sie nach Abschluss der Aufgabe auszuführen. Sie können einen Rückruf beispielsweise verwenden, um Daten zu verarbeiten, wenn diese von einem Server eintreffen.

Bei komplexen Vorgängen kann die Verwendung von Rückrufen jedoch ziemlich chaotisch werden. Dieses Durcheinander ist als „Callback-Hölle“ bekannt, bei der ein Callback innerhalb eines anderen stattfinden kann, was den Code unlesbar und unkontrollierbar macht.

Callback Hell Beispiel:

    fetchData((data) => {
      processData(data, (processedData) => {
        saveData(processedData, (result) => {
          console.log(result);
        });
      });
    });

Wie oben gezeigt, wird es aufgrund seiner tief verschachtelten Struktur, die oft als „Callback-Hölle“ bezeichnet wird, in größeren Codebasen immer schwieriger zu lesen und zu warten.

Um dieses Problem anzugehen, wurden Versprechen eingeführt, die eine sauberere und besser organisierte Möglichkeit bieten, asynchrone Aufgaben zu bearbeiten, indem eine Verkettung auf eine besser lesbare Art und Weise ermöglicht wird.

Versprechensbasierter Ansatz:

    fetchData((data) => {
      processData(data, (processedData) => {
        saveData(processedData, (result) => {
          console.log(result);
        });
      });
    });

Dieser Ansatz flacht die Struktur ab und macht den Code lesbarer und wartbarer.

Wie funktionieren Versprechen?

Promises in JavaScript können einen von drei Zuständen haben:

  1. Ausstehend: Dies ist der erste Schritt. Das Versprechen muss noch erfüllt werden.

  2. Erfüllt: Das Versprechen wurde erfolgreich erfüllt, was bedeutet, dass es gelöst ist und einen Wert hat.

  3. Abgelehnt: Das Versprechen wurde nicht erfolgreich abgeschlossen und enthält eine Fehlermeldung.

Grundlegende Syntax

fetchData()
  .then(processData)
  .then(saveData)
  .then(console.log)
  .catch(console.error);

In diesem Beispiel wird das Versprechen nach 1 Sekunde mit der Meldung „Versprechen gelöst!“ aufgelöst. Die Methode.then() wird verwendet, um den aufgelösten Wert zu verarbeiten.

Umgang mit Versprechen

Verwendung von .then() für die Erfolgsbehandlung

Die.then()-Methode wird verwendet, um zu handhaben, was passiert, wenn ein Versprechen erfolgreich abgeschlossen wird. Es registriert Funktionen (Rückrufe), die ausgeführt werden sollen, wenn das Versprechen erfüllt ist.

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("Promise resolved!");
  }, 1000);
});

myPromise.then(result => console.log(result));

Verwendung von .catch() zur Fehlerbehandlung

Die.catch()-Methode wird verwendet, um zu handhaben, was passiert, wenn ein Versprechen fehlschlägt. Es registriert eine Funktion (Rückruf), die ausgeführt wird, wenn das Versprechen abgelehnt wird.

myPromise.then(data => {
  console.log("Data received:", data);
});

Verwendung von .finally() zur Bereinigung

Mit der.finally()-Methode können Sie Code ausführen, nachdem das Versprechen erfüllt wurde, unabhängig davon, ob es erfolgreich war oder nicht.

myPromise.catch(error => {
  console.error("Error:", error);
});

Versprechen verketten

Durch die Verkettung können Sie Aufgaben nacheinander ausführen, indem Sie das Ergebnis der vorherigen Aufgabe übergeben. Fahren Sie dann mit next.then() fort. Dadurch können Sie mehrere asynchrone Aufgaben nacheinander bearbeiten.

Beispiel für die Verkettung:

myPromise.finally(() => {
  console.log("Cleanup tasks");
});

In diesem Beispiel wird every.then() verwendet, um jeden Schritt im Prozess abzuwickeln und so einen klaren Datenfluss zu ermöglichen. Dadurch können Sie sehen, wie das Ergebnis einer Stufe auf die nächste übertragen wird.

Fehlerbehandlung in Versprechen

Promises vereinfachen die Fehlerbehandlung, indem sie die Weitergabe der Kette an die.catch()-Methode zur Lösung ermöglichen. Dadurch entfällt die Notwendigkeit, Fehler in jeder Phase zu behandeln, sodass Ihr Code klarer und einfacher zu verwalten ist.

Beispiel mit Fehlerfortpflanzung:

fetch('https://api.example.com/user')
  .then(response => response.json())
  .then(data => {
    console.log("Processed data:", data);
    return processData(data);
  })
  .then(finalResult => {
    console.log("Final result:", finalResult);
  })
  .catch(error => console.error("Error:", error));

Wenn ein Schritt in der Versprechenskette fehlschlägt, wird der Fehler vom.catch()-Block abgefangen. Dies macht es einfach, Probleme zu lösen und dafür zu sorgen, dass Ihr Code reibungslos läuft.

Erweiterte Promise-Funktionen

1. Promise.all() für parallele Ausführung

Mit der Promise.all()-Methode können Sie mehrere Versprechen gleichzeitig ausführen und warten, bis sie alle abgeschlossen sind. Wenn alle Versprechen erfüllt sind, erhalten Sie die Ergebnisse jedes einzelnen. Wenn ein Versprechen fehlschlägt, erkennt es den Fehler.

fetchData()
  .then(processData)
  .then(saveData)
  .catch(error => console.error("An error occurred:", error));

Wenn in diesem Beispiel ein Versprechen fehlschlägt, schlägt das gesamte Promise.all() fehl.

2. Promise.race() für das schnellste Versprechen

Die Promise.race()-Methode gibt das Ergebnis des ersten Versprechens zurück, das abgeschlossen wird, unabhängig davon, ob es erfolgreich ist oder fehlschlägt.

    fetchData((data) => {
      processData(data, (processedData) => {
        saveData(processedData, (result) => {
          console.log(result);
        });
      });
    });

In diesem Beispiel wird das Ergebnis des Versprechens (fetchData1 oder fetchData2), das zuerst abgeschlossen wird, in der Konsole protokolliert.

3. Promise.allSettled() für die Handhabung aller Ergebnisse

Die Promise.allSettled()-Methode wartet darauf, dass sich alle Versprechen, die Sie ihr geben, in einem erfolgreichen oder fehlgeschlagenen Zustand befinden, und wird dann beendet. Anschließend wird ein Array zurückgegeben, das die Ergebnisse jedes Versprechens enthält.

fetchData()
  .then(processData)
  .then(saveData)
  .then(console.log)
  .catch(console.error);

In diesem Beispiel wartet Promise.allSettled() darauf, dass sowohl fetchData1() als auch fetchData2() abgeschlossen sind. Anschließend werden der Status und das Ergebnis (oder der Fehler) jedes Versprechens protokolliert. Auf diese Weise können Sie sehen, was mit jedem Versprechen passiert ist, unabhängig davon, ob es erfolgreich war oder nicht.

4.Promise.any() zur Lösung mit dem ersten erfolgreichen Versprechen

Die Promise.any()-Methode wartet darauf, dass das erste Versprechen aus einer Liste von Versprechen korrekt aufgelöst wird. Falls mindestens ein Versprechen gelöst wird, wird der Wert von der Promise.any()-Methode zurückgegeben. Wenn alle Versprechen abgelehnt werden, gibt diese Methode einen Fehler aus.

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("Promise resolved!");
  }, 1000);
});

myPromise.then(result => console.log(result));

In diesem Beispiel wartet Promise.any() darauf, dass das erste Versprechen erfolgreich gelöst wird. Die Prozedur gibt das Ergebnis des ersten erfolgreichen Versprechens zurück, in diesem Fall Versprechen2 mit dem Wert „Erfolg A“. Wenn alle Versprechen abgelehnt werden, wird der Block.catch() ausgeführt und die Fehlermeldung protokolliert. Diese Strategie ist von Vorteil, wenn Sie das Ergebnis des ersten erfolgreichen Versprechens erhalten möchten, ohne auf den Rest warten zu müssen.

JavaScript-Ausführungsablauf mit Versprechen (wichtig)

1. Versprechen in JavaScript werden in der Mikrotask-Warteschlange ausgeführt, die Vorrang vor Makrotasks wie setTimeout hat.

Hier ist ein Beispiel, um dies zu veranschaulichen:

myPromise.then(data => {
  console.log("Data received:", data);
});

In diesem Beispiel:

  • console.log(2) wird zuerst ausgeführt, da es sich um einen regulären synchronen Vorgang handelt.

  • console.log (6) wird als nächstes ausgeführt, da es ebenfalls synchron ist.

  • Promise’s.then() wird vor dem setTimeout-Rückruf ausgeführt, da Versprechen Mikrotasks sind, die eine höhere Priorität haben, und gibt daher 3 aus.

  • Schließlich wird der setTimeout-Callback ausgeführt, da es sich um eine Makrotask handelt, und gibt 4 aus.

Denken Sie also immer daran, dass das Versprechen’s.then() aufgrund der Priorität der Mikrotask-Warteschlange vor dem setTimeout-Rückruf ausgeführt wird.

2. Versprechen Sie die Ausführungsreihenfolge und die Microtask-Warteschlange mit mehreren .then()-Aufrufen

In JavaScript wird Code in einer bestimmten Reihenfolge ausgeführt: zuerst der synchrone Code, dann Mikrotasks (wie Versprechen) und schließlich Makrotasks (wie setTimeout).

Hier ist ein Beispiel, um dies zu erklären:

    fetchData((data) => {
      processData(data, (processedData) => {
        saveData(processedData, (result) => {
          console.log(result);
        });
      });
    });

In diesem Beispiel wird synchroner Code zuerst ausgeführt und protokolliert 3, 6, 2, 7 und 8. Sobald der synchrone Code beendet ist, werden Mikrotasks (die.then()-Rückrufe) verarbeitet und 1 und 9 protokolliert. Schließlich Makrotasks (von setTimeout) werden in der Reihenfolge ihrer Verzögerungen ausgeführt und protokollieren 21 (0 ms) und 13 (10 ms). Dadurch wird die Ausführungsreihenfolge von JavaScript hervorgehoben: synchroner Code > Mikroaufgaben > Makroaufgaben.

3. Mehrere Lösungs- und Ablehnungsaufrufe in einem Versprechen: Nur der erste zählt

Wenn Sie ein Versprechen erstellen, zählt nur der erste Aufruf zur Lösung oder Ablehnung. Alle anderen Anrufe werden abgewiesen.

Hier ist ein Beispiel, um dies zu veranschaulichen:

fetchData()
  .then(processData)
  .then(saveData)
  .then(console.log)
  .catch(console.error);

In diesem Beispiel wird das Versprechen mit dem Wert 1 gelöst. Die zweite Lösung und die Ablehnungsaufrufe werden ignoriert, da das Versprechen bereits mit der ersten Lösung erfüllt wurde.

4. Verketten von Versprechen und Behandeln von Werten in sequentiellen .then()-Aufrufen

Wenn Sie Versprechen verketten, verarbeitet every.then() einen Schritt im Prozess.

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("Promise resolved!");
  }, 1000);
});

myPromise.then(result => console.log(result));

In diesem Beispiel beginnt Promise.resolve(1) mit einem Wert von 1, aber das erste .then(() => 2) gibt stattdessen 2 zurück. Das nächste .then(3) wird ignoriert und der Wert 2 übergeben. .then((value) => value * 3) multipliziert den Wert mit 3, was 6 ergibt. .then(Promise.resolve(4)) ändert den Wert nicht und schließlich .then(console. log) protokolliert 6. Dies zeigt, wie Werte durch die Kette weitergeleitet werden, wobei Nicht-Funktionswerte ignoriert werden.

5. Versprechenskette mit .catch()- und .finally()-Behandlung

myPromise.then(data => {
  console.log("Data received:", data);
});

In diesem Beispiel verketten wir mehrere Methoden.then(),.catch() und.finally() miteinander, um zu zeigen, wie verschiedene Phasen der Versprechensauflösung gehandhabt werden. Lassen Sie es uns aufschlüsseln:

  • finally() erhält kein Argument:
    Der „final()“-Block führt Bereinigungscode aus, akzeptiert oder übergibt jedoch keine Werte. Es wird verwendet, um sicherzustellen, dass bestimmter Code unabhängig vom Ergebnis des Versprechens ausgeführt wird.

  • Die Rückgabe eines Werts in „final()“ hat keinen Einfluss auf das Versprechen:
    Wenn Sie im Block „final()“ einen Wert zurückgeben, hat dies keinen Einfluss auf die Versprechenskette oder den Endwert. Es wird nach der Auflösung/Ablehnung des Versprechens ausgeführt, verändert jedoch nicht das Ergebnis.

  • Das Auslösen eines Fehlers in „final()“ führt zur Ablehnung:
    Wenn Sie in „final()“ einen Fehler auslösen oder ein abgelehntes Versprechen zurückgeben, führt dies dazu, dass die Versprechenskette mit dem Fehler oder dem Ablehnungsgrund abgelehnt wird.

myPromise.catch(error => {
  console.error("Error:", error);
});

ODER

myPromise.finally(() => {
  console.log("Cleanup tasks");
});
  • Die Reihenfolge von then() und Catch() ist wichtig .then() und .catch() können in beliebiger Reihenfolge aufgerufen werden, sie geben jedoch immer den Endzustand des Versprechens zurück. Wenn ein Versprechen von .catch() verarbeitet wird, erhält jedes nachfolgende .then() den endgültigen Wert.

Beispiel:

    fetchData((data) => {
      processData(data, (processedData) => {
        saveData(processedData, (result) => {
          console.log(result);
        });
      });
    });

Konvertieren von Promise-Ketten in Async/Await

Async/await ist eine Methode zur Verwendung von Versprechen, die dazu führt, dass der Code dem im synchronen Modus geschriebenen Code ähnlicher wird. Der häufig verwendete Begriff ist „syntaktischer Zucker“, da er einen einfacheren und saubereren Weg zur Erstellung von asynchronem Code bietet.

fetchData()
  .then(processData)
  .then(saveData)
  .then(console.log)
  .catch(console.error);

Versprechen mit Async/Await kombinieren

Mit Promise.all() können Sie Versprechen mit „async/await“ zur parallelen Ausführung kombinieren.

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("Promise resolved!");
  }, 1000);
});

myPromise.then(result => console.log(result));

Best Practices und häufige Fehler

  • Vermeiden Sie Deep Nesting:Verwenden Sie Verkettung oder Async/Await, um den Code flach und lesbar zu halten.

  • Fehler immer behandeln: Stellen Sie sicher, dass jede Promise-Kette einen.catch() oder einen Try/Catch-Block hat.

  • Verwenden Sie die parallele Ausführung mit Bedacht: Verwenden Sie Promise.all() nur, wenn Aufgaben unabhängig sind, aber gemeinsam abgeschlossen werden müssen.

Abschluss

JavaScript-Versprechungen sind eine der besten Möglichkeiten, Ihre zeitaufwändigen Vorgänge zu bewältigen, wie zum Beispiel das Abrufen von Daten auf einem Server. Sie helfen Ihnen sogar dabei, saubereren und einfacher zu wartenden Code zu schreiben, und die Anwendung des Gelernten wird Sie in die Lage versetzen, die Vorteile der asynchronen Codierung voll auszuschöpfen. Sobald Sie praktische Erfahrung gesammelt haben und anfangen, elegant mit Fehlern umzugehen, werden Versprechen zu einem so großen Teil von JavaScript.

Vielen Dank fürs Lesen! Wenn Sie diesen Artikel hilfreich finden, markieren Sie ihn gerne, klatschen Sie, hinterlassen Sie einen Kommentar oder kontaktieren Sie mich sogar auf Twitter/X und LinkedIn, da er sehr geschätzt wird und dazu beiträgt, dass Inhalte wie dieser kostenlos bleiben!

Das obige ist der detaillierte Inhalt vonAlles, was Sie über JavaScript-Versprechen und deren Funktionsweise wissen müssen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn