Grundlegendes zu JavaScript-Versprechen

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'); //   reject('Promise rejected'); //       }); 

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); //  '  !' }, (error) => { console.log(error); //   } ); 

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); // Promise1  return promise2; }) .then((data) => { console.log(data); // Promise2  return promise3; }) .then((data) => { console.log(data); }) .catch((error) => { console.log(error); // Promise3  }); 

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); // Promise1  promise2.then((data) => { console.log(data); // Promise2  promise3.then((data) => { console.log(data); }).catch((error) => { console.log(error); // Promise3  }); }).catch((error) => { console.log(error); }) }).catch((error) => { console.log(error); }); 

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)); // Promise2  

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)) // Promise1  .catch((error) => console.log(error)); 

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 - Rennen

Fazit


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!

Source: https://habr.com/ru/post/de439746/


All Articles