Guten Tag, Habr! Ich präsentiere Ihnen die Übersetzung des Artikels
„Versprechen in JavaScript verstehen“ von Sukhjinder Arora.
Vom Autor der Übersetzung: Neben dem Autor selbst hoffe ich, dass der Artikel für Sie nützlich war. Bitte, wenn sie Ihnen wirklich geholfen hat, etwas Neues für sich selbst zu lernen, dann seien Sie nicht zu faul, um zum Originalartikel zu gehen und dem Autor zu danken! Ich freue mich über Ihr Feedback!
Link zur Übersetzung des Artikels über asynchrones JavaScript desselben Autors .JavaScript ist eine Single-Threaded-Programmiersprache, was bedeutet, dass jeweils eine Aufgabe ausgeführt werden kann. Vor ES6 haben wir Rückrufe verwendet, um asynchrone Aufgaben wie Netzwerkanforderungen zu verwalten.
Mit Versprechungen können wir „Höllenrückrufe“ vermeiden und unseren Code sauberer, lesbarer und verständlicher machen.
Angenommen, wir möchten einige Daten asynchron vom Server abrufen und mithilfe von Rückrufen Folgendes tun:
getData(function(x){ console.log(x); getMoreData(x, function(y){ console.log(y); getSomeMoreData(y, function(z){ console.log(z); }); }); });
Hier
fordere ich einige Daten vom Server mit der Funktion
getData () an , die Daten innerhalb der Rückruffunktion empfängt. Innerhalb der Rückruffunktion
fordere ich zusätzliche Daten an, indem
ich die Funktion
getMoreData () aufrufe , die vorherigen Daten als Argument übergebe und so weiter.
Dies ist das, was wir als "Rückrufhölle" bezeichnen, bei der jeder Rückruf in den anderen verschachtelt ist und jeder interne Rückruf von seinem übergeordneten Element abhängt.
Wir können das obige Snippet mit Versprechungen umschreiben:
getData() .then((x) => { console.log(x); return getMoreData(x); }) .then((y) => { console.log(y); return getSomeMoreData(y); }) .then((z) => { console.log(z); });
Sie können sehen, was besser lesbar geworden ist als beim ersten Rückrufbeispiel.
Was sind Versprechen?
Ein Versprechen (Promise) ist ein Objekt, das den zukünftigen Wert einer asynchronen Operation enthält. Wenn Sie beispielsweise einige Daten vom Server anfordern, verspricht Promis, diese Daten zu erhalten, die wir in Zukunft verwenden können.
Bevor wir uns mit all diesen technischen Dingen befassen, schauen wir uns die Terminologie der Versprechen an.
Versprechen Staaten
Ein Versprechen in JavaScript hat wie ein Versprechen im wirklichen Leben drei Zustände. Dies kann 1) ungelöst (ausstehend), 2) gelöst / gelöst (abgeschlossen) oder 3) abgelehnt / abgelehnt sein.
Ungelöst oder ausstehend - Promis wartet, wenn das Ergebnis nicht fertig ist. Das heißt, es erwartet den Abschluss von etwas (zum Beispiel den Abschluss einer asynchronen Operation).
Gelöst oder abgeschlossen - Promis wurden aufgelöst, wenn das Ergebnis verfügbar ist. Das heißt, etwas hat seine Ausführung abgeschlossen (zum Beispiel eine asynchrone Operation) und alles ist gut gelaufen.
Abgelehnt - Promis abgelehnt, wenn während der Ausführung ein Fehler aufgetreten ist.
Jetzt wissen wir, was Promis und seine Terminologie sind. Kehren wir zum praktischen Teil der Versprechen zurück.
Promis erstellen
In den meisten Fällen verwenden Sie einfach Versprechen und erstellen sie nicht. Es ist jedoch wichtig zu wissen, wie sie erstellt werden.
Syntax:
const promise = new Promise((resolve, reject) => { ... });
Wir haben mit dem Promises-Konstruktor ein neues Versprechen erstellt. Es wird ein Argument verwendet, ein Rückruf, der auch als ausführende Funktion bezeichnet wird. Dabei werden zwei Rückrufe ausgeführt, aufgelöst und
abgelehnt .
Die Exekutivfunktion wird unmittelbar nach der Erstellung des Versprechens ausgeführt. Ein Versprechen wird durch Aufrufen von
entschlossen () abgegeben und durch
Zurückweisen () abgelehnt. Zum Beispiel:
const promise = new Promise((resolve, reject) => { if(allWentWell) { resolve(' !'); } else { reject('- '); } });
lösen () und
ablehnen () nehmen ein Argument an, das eine Zeichenfolge, eine Zahl, ein logischer Ausdruck, ein Array oder ein Objekt sein kann.
Schauen wir uns ein anderes Beispiel an, um zu verstehen, wie Versprechen entstehen.
const promise = new Promise((resolve, reject) => { const randomNumber = Math.random(); setTimeout(() => { if(randomNumber < .6) { resolve(' !'); } else { reject('- '); } }, 2000); });
Hier habe ich mit dem Promis-Konstruktor ein neues Versprechen erstellt. Ein Versprechen wird 2 Sekunden nach seiner Erstellung ausgeführt oder abgelehnt. Ein Versprechen wird ausgeführt, wenn
randomNumber kleiner als .6 ist und in anderen Fällen abgelehnt wird.
Wenn ein Versprechen erstellt wurde, steht es noch aus und sein Wert ist nicht
definiert .
Nach 2 Sekunden endet der Timer, das Versprechen wird zufällig entweder ausgeführt oder abgelehnt, und sein Wert ist derjenige, der an die
Auflösungs- oder
Ablehnungsfunktion übergeben wird. Unten finden Sie ein Beispiel für zwei Fälle:
Erfolgreicher Abschluss:

Versprechen ablehnen:
Hinweis: Versprechen können nur einmal ausgeführt oder abgelehnt werden. Weitere Aufrufe zum
Auflösen () oder
Ablehnen () haben keinerlei Auswirkungen auf den Status des Versprechens. Ein Beispiel:
const promise = new Promise((resolve, reject) => { resolve('Promise resolved');
Da
resolve () zuerst aufgerufen wurde, hat das Versprechen jetzt den Status "abgeschlossen". Der nachfolgende Aufruf zur
Ablehnung () hat keinerlei Auswirkungen auf den Status des Versprechens.
Promis verwenden
Jetzt wissen wir, wie man Versprechen erstellt. Lassen Sie uns nun herausfinden, wie Sie das bereits erstellte Versprechen anwenden können. Wir verwenden Versprechen mit den Methoden
then () und
catch () .
Beispiel: Abfragen von Daten von einer API mithilfe von
Fetch , wodurch ein Versprechen zurückgegeben wird.
.then () Syntax: versprechen.then (successCallback, failedCallback)successCallback wird aufgerufen, wenn das Versprechen erfolgreich ausgeführt wurde. Es wird ein Argument benötigt, nämlich der Wert, der an
resolve () übergeben wird .
failCallback wird aufgerufen, wenn das Versprechen abgelehnt wurde. Es wird ein Argument benötigt, nämlich der Wert, der angegeben wird,
um (() abzulehnen .
Ein Beispiel:
const promise = new Promise((resolve, reject) => { const randomNumber = Math.random(); if(randomNumber < .7) { resolve(' !'); } else { reject(new Error('- ')); } }); promise.then((data) => { console.log(data);
Wenn das Versprechen ausgeführt wurde, wird
successCallback mit dem an
Auflösung übergebenen Wert
aufgerufen () . Und wenn das Versprechen abgelehnt wurde, wird
failCallback mit dem Wert
aufgerufen, der an
reverse () übergeben wurde.
.catch () -Syntax : Versprechen.Catch (FailureCallback)Wir verwenden
catch () , um Fehler zu behandeln. Dies ist besser lesbar als die Fehlerbehandlung in
failCallback innerhalb des Rückrufs der
then () -Methode.
const promise = new Promise((resolve, reject) => { reject(new Error('- ')); }); promise .then((data) => { console.log(data); }) .catch((error) => { console.log(error);
Versprechen Kette
Die Methoden
then () und
catch () können auch ein neues Versprechen zurückgeben, das von einer Kette anderer then () am Ende der vorherigen then () -Methode verarbeitet werden kann.
Wir verwenden eine Kette von Versprechungen, wenn wir eine Folge von Versprechungen erfüllen wollen.
Zum Beispiel:
const promise1 = new Promise((resolve, reject) => { resolve('Promise1 '); }); const promise2 = new Promise((resolve, reject) => { resolve('Promise2 '); }); const promise3 = new Promise((resolve, reject) => { reject('Promise3 '); }); promise1 .then((data) => { console.log(data);
Also, was ist hier los?
Wenn
Versprechen1 erfüllt ist, wird die Methode
then () aufgerufen
, die Versprechen2 zurückgibt.
Wenn
Versprechen2 erfüllt ist ,
wird () erneut aufgerufen und gibt
Versprechen3 zurück .
Da Versprechen3 abgelehnt wird, wird anstelle des nächsten
then () catch () aufgerufen, das die Ablehnung von
Versprechen3 behandelt .
Hinweis: In der Regel reicht eine
catch () -Methode aus, um die Ablehnung von Versprechungen in der Kette zu handhaben, wenn diese Methode am Ende steht.
Häufiger Fehler
Viele Newcomer machen einen Fehler, indem sie einige Versprechen in andere investieren. Zum Beispiel:
const promise1 = new Promise((resolve, reject) => { resolve('Promise1 '); }); const promise2 = new Promise((resolve, reject) => { resolve('Promise2 '); }); const promise3 = new Promise((resolve, reject) => { reject('Promise3 '); }); promise1.then((data) => { console.log(data);
Obwohl dies gut funktioniert, wird es als schlechter Stil angesehen und macht den Code weniger lesbar. Wenn Sie eine Reihe von Versprechungen ausführen müssen, ist es besser, sie nacheinander zu platzieren, als sie ineinander zu setzen.
Promise.all ()
Diese Methode nimmt ein Array von Versprechungen entgegen und gibt ein neues Versprechen zurück, das ausgeführt wird, wenn alle Versprechen innerhalb des Arrays ausgeführt oder abgelehnt werden, sobald ein abgelehntes Versprechen gefunden wird. Zum Beispiel:
const promise1 = new Promise((resolve, reject) => { setTimeout(() => { resolve('Promise1 '); }, 2000); }); const promise2 = new Promise((resolve, reject) => { setTimeout(() => { resolve('Promise2 '); }, 1500); }); Promise.all([promise1, promise2]) .then((data) => console.log(data[0], data[1])) .catch((error) => console.log(error));
Hier ist das Argument in
then () ein Array, das die Werte der Versprechen in derselben Reihenfolge enthält, in der sie an
Promise.all () übergeben wurden . (Nur wenn alle Versprechen ausgeführt werden)
Das Versprechen wird mit der Ursache für die Ablehnung des ersten Versprechens im übertragenen Array abgelehnt. Zum Beispiel:
const promise1 = new Promise((resolve, reject) => { setTimeout(() => { resolve('Promise1 '); }, 2000); }); const promise2 = new Promise((resolve, reject) => { setTimeout(() => { reject('Promise2 '); }, 1500); }); Promise.all([promise1, promise2]) .then((data) => console.log(data[0], data[1])) .catch((error) => console.log(error));
Hier haben wir zwei Versprechen, wobei eines nach 2 Sekunden ausgeführt wird und das andere nach 1,5 Sekunden abweicht. Sobald das zweite Versprechen abgelehnt wird, wird das von
Promise.all () zurückgegebene Versprechen abgelehnt, ohne auf das erste zu warten.
Diese Methode kann nützlich sein, wenn Sie mehr als ein Versprechen haben und wissen möchten, wann alle Versprechen erfüllt sind. Zum Beispiel, wenn Sie Daten von einer Drittanbieter-API anfordern und nur dann etwas mit diesen Daten tun möchten, wenn alle Anforderungen erfolgreich sind.
Als Ergebnis haben wir
Promise.all () , das auf die erfolgreiche Ausführung aller Versprechen wartet oder seine Ausführung abschließt, wenn es den ersten Fehler im Array von Versprechen erkennt.
Promise.race ()
Diese Methode akzeptiert ein Array von Versprechungen und gibt ein neues Versprechen zurück, das ausgeführt wird, sobald das erfüllte Versprechen im Array erfüllt oder abgelehnt wird, wenn das abgelehnte Versprechen früher auftritt. Zum Beispiel:
const promise1 = new Promise((resolve, reject) => { setTimeout(() => { resolve('Promise1 '); }, 1000); }); const promise2 = new Promise((resolve, reject) => { setTimeout(() => { reject('Promise2 '); }, 1500); }); Promise.race([promise1, promise2]) .then((data) => console.log(data))
Hier haben wir zwei Versprechen, wobei eines nach 1 Sekunde ausgeführt wird und das andere nach 1,5 Sekunden abweicht. Sobald das erste Versprechen erfüllt ist, hat das von Promise.race () zurückgegebene Versprechen den Status erfüllt, ohne auf den Status des zweiten Versprechens zu warten.
Hier sind die
Daten , die an
then () übergeben werden, der Wert des ersten ausgeführten Versprechens.
Infolgedessen wartet
Promise.race () auf das erste Versprechen und nimmt seinen Status als Status des zurückgegebenen Versprechens an.
Kommentar des Autors der Übersetzung: Daher der Name selbst. Rennen - RennenFazit
Wir haben in JavaScript gelernt, was Versprechen sind und was sie essen. Versprechen bestehen aus zwei Teilen 1) Erstellen Sie ein Versprechen und 2) Verwenden Sie ein Versprechen. Meistens verwenden Sie Versprechen, anstatt sie zu erstellen, aber es ist wichtig zu wissen, wie sie erstellt werden.
Das ist alles, ich hoffe, dieser Artikel hat Ihnen geholfen!