Im ersten Teil dieses Tutorials haben wir die Prinzipien der asynchronen Programmierung und der Verwendung von Rückrufen kennen gelernt. Um zu überprüfen, asynchrones Programmieren ermöglicht uns das Schreiben von Code, der nicht blockiert wird, indem Blockieraufgaben später ausgeführt werden. Callback-Funktionen bieten eine Möglichkeit, die Ausführung unseres Codes zu synchronisieren.
Das wiederholte Verschachteln von Rückrufen ist jedoch kein gutes Muster. Hier kommen Versprechen zur Rettung. In JavaScript-Bibliotheken wurden schon seit einiger Zeit Versprechungen verwendet, jetzt können Sie sie nativ in Ihrem Code verwenden. Async-Funktionen verbessern die Versprechungen, indem sie uns erlauben, unsere Aufgaben nacheinander zu schreiben, ohne dass wir uns über den Zeitpunkt ihrer Ausführung Gedanken machen müssen.
Lassen Sie uns einen Blick darauf werfen, was ein Versprechen konzeptionell ist. Stellen Sie sich das Szenario vor, in dem Sie online einkaufen und ein Paar Schuhe kaufen. Wenn Sie auschecken, erhalten Sie eine Zusammenfassung Ihres Einkaufs per E-Mail.
Diese Auftragsbestätigung ist wie ein Versprechen. Das Versprechen ist Ihre Garantie, dass Sie später etwas vom Unternehmen zurückbekommen. Während Ihre Bestellung noch aussteht, hört Ihr Leben natürlich nicht auf. Sie erledigen andere Aufgaben wie das Surfen im Internet. Wenn Ihre Bestellung erfüllt ist, erhalten Sie eine E-Mail mit den Versandinformationen. Es ist möglich, dass Ihre Bestellung abgelehnt wird. Der von Ihnen bestellte Artikel ist möglicherweise nicht auf Lager oder es liegt ein Problem mit Ihrer Zahlungsmethode vor. In diesem Fall erhalten Sie eine E-Mail, die Sie über den Fehler informiert.
Im Code ist ein Versprechen ein Objekt, das sicherstellt, dass wir einen zukünftigen Wert für unsere Anfrage erhalten, ob sie erfolgreich ist oder nicht. Dies ist das allgemeine Formular zum Erstellen und Verwenden eines Versprechens:
function task1 () return new Promise (Funktion (Auflösen, Ablehnen) Auflösen (Daten); Ablehnen (Fehler);); task1 () .then (Funktion (Ergebnis) console.log (Ergebnis);) .catch (Funktion (Fehler) Konsole.log (Fehler););
Um ein Versprechen zu erstellen, instantiieren Sie ein Versprechungsobjekt und schreiben Ihren asynchronen Code in die Callback-Funktion des Versprechens. Die Daten, die Sie aus dem Versprechen zurückgeben möchten, werden als Argument an die übergeben Entschlossenheit
Funktion und Ihre Fehlermeldung wird an die übergeben ablehnen
Funktion. Wir verketten Versprechen mit der dann
Methode. Dadurch können wir die Aufgaben nacheinander ausführen.
Wenn wir die Ergebnisse einer Aufgabe an die nächste Aufgabe übergeben müssen, geben wir sie in der Datenbank zurück dann
Methode. Wir möchten möglicherweise Versprechen miteinander verketten, wenn wir an der Umwandlung von Werten interessiert sind oder unseren Code in einer bestimmten Reihenfolge ausführen müssen. Am Ende der Kette fangen wir unsere Fehler auf. Wenn bei einer unserer Aufgaben ein Fehler auftritt, werden die verbleibenden Aufgaben übersprungen und der Fehler an unseren catch-Block gesendet.
In Teil 1 dieses Tutorials haben wir Rückrufe verwendet, um eine Datei zu öffnen und einen Beitrag und seine Kommentare abzurufen. So sieht der komplette Code mit Versprechungen aus:
const fs = required ('fs'); const Pfad = Anfordern ('Pfad'); const postsUrl = pfad.join (__ dirname, 'db / posts.json'); const commentsUrl = pfad.join (__ dirname, 'db / comments.json'); // Rückgabe der Daten aus unserer Datei function loadCollection (url) return new Promise (Funktion (Auflösen, Ablehnen)) fs.readFile (Url, 'utf8'), Funktion (Fehler, Daten) if (error) reject (' error '); else resol (JSON.parse (data)););); // Rückgabe eines Objekts anhand der ID Funktion getRecord (Auflistung, ID) Rückgabe neuer Promise (Funktion (Auflösen, Ablehnen)) const data = collection.find (Funktion (Element) return element.id == id;); auflösen (Daten);); // ein Array von Kommentaren für eine Post-Funktion zurückgeben getCommentsByPost (comments, postId) return comments.filter (function (comment) return comment.postId == postId;); // Initialisierungscode loadCollection (postsUrl) .then (function (posts) return getRecord (posts, "001");) .then (function (post) console.log (post); return loadCollection (commentsUrl); ) .then (Funktion (Kommentare) const postComments = getCommentsByPost (Kommentare "001"); console.log (postComments);) .catch (function (error) console.log (error););
Der Unterschied hier ist, dass unsere Methode zum Öffnen der Datei jetzt in ein Versprechungsobjekt eingeschlossen ist. Und anstatt unsere Aufgaben mit Rückrufen zu verschachteln, werden sie mit verkettet dann
.
Wie Sie sehen, haben wir die Notwendigkeit für Rückrufe nicht beseitigt. Wir benutzen sie einfach anders. Vorher haben wir unsere Rückrufe geschachtelt, damit wir die Ausführung unseres Codes in der nächsten Aufgabe fortsetzen können.
Dies erinnert mich daran, wenn ich den Kundendienst wegen eines Problems anrufe, und anstatt dass der Agent mein Problem löst, werde ich zu jemand anderem weitergeleitet. Es kann sein, dass eine andere Person den Anruf auflöst oder nicht, aber für den ersten Agenten ist dies die Verantwortung einer anderen Person.
Mit Versprechen bekommen wir etwas zurück, bevor wir zur nächsten Aufgabe gehen. Wenn wir das zur nächsten Fortführung unseres Codes tragen müssen, können wir ein dann
Aussage.
Schreiben Sie mit Hilfe von Versprechen ein Programm, das eine Benutzerdatei öffnet, die Benutzerinformationen abruft und dann eine Beitragsdatei öffnet und alle Beiträge des Benutzers druckt.
Versprechen sind eine Verbesserung in der Gestaltung unseres Programms, aber wir können es besser machen. Es wäre sehr praktisch, wenn wir unsere Aufgaben synchron wie folgt ausführen könnten:
Aufgabe 1(); task2 (); task3 ();
Nun, wir können mit dem Async / Erwarten-Muster. Dazu packen wir unsere Aufgaben in eine asynchrone Funktion. Diese Funktion liefert ein Versprechen. Dann implementieren wir die Fehlerbehandlung, indem wir unsere Aufgaben in a einschließen versuchen / fangen
Aussage.
Wenn das Versprechen erfüllt wird, wird es alle Aufgaben erfüllen, die in unserem Unternehmen waren Versuchen
Block. Wenn es abgelehnt wird, die Fang
Block wird ausgeführt. Hinzufügen der erwarten
Das Schlüsselwort vor einer Aufgabe hält unser Programm an, bis die Aufgabe abgeschlossen ist.
Dies ist das allgemeine Formular für die Verwendung von asynchronen Funktionen:
async-Funktion initTasks () try const a = waitit task1 (); const b = Erwarte Task2 (); const c = Erwarte Task3 (); // etwas mit a, b und c tun catch (error) // etwas mit dem Fehlerobjekt tun initTasks ();
Mit diesem Muster können wir die Ausführung unseres Codes in unserem Dateibeispiel umschreiben.
async function getPost () try const posts = await loadCollection (postsUrl); const post = waitRecord (Beiträge, "001"); const comments = await loadCollection (commentsUrl); const postComments = Erwarte getCommentsByPost (Kommentare, post.id); console.log (Beitrag); console.log (postComments); catch (Fehler) console.log (Fehler); getPost ();
Ich mag es, unseren asynchronen Code mit einem versuchen / fangen
Anweisung, da sie Fehlerbehandlungscode eindeutig von regulärem Code trennt. Wenn einer der Codes in unserem Versuchen
Block verursacht einen Fehler, wird von der behandelt Fang
Block. Außerdem können wir eine hinzufügen endlich
Block, der Code ausführt, unabhängig davon, ob unsere Aufgaben erfolgreich sind oder nicht.
Ein Beispiel für die Verwendung dieses Musters ist, wenn Bereinigungscode ausgeführt werden muss. Dieser Code muss nicht unbedingt in einem enthalten sein endlich
Block. Es kann nach dem geschrieben werden Fang
Anweisung, und es wird ausgeführt. Versprechen haben diese Syntax nicht eingebaut. Wir müssten eine andere verketten dann
Aussage nach unserer Fang
Aussage, um den gleichen Effekt zu erzielen.
Schreiben Sie mit async / await ein Programm, das eine Benutzerdatei öffnet, die Benutzerinformationen abruft und dann eine Datei mit Beiträgen öffnet und die Benutzerinformationen und alle ihre Beiträge druckt.
Rückrufe sind nicht von Natur aus böse. Das Übergeben von Funktionen an andere Funktionen ist in JavaScript ein nützliches Muster. Rückrufe werden zu einem Problem, wenn wir sie verwenden, um den Ablauf unserer Anwendungslogik zu steuern. Da JavaScript asynchron ist, müssen wir darauf achten, wie wir unseren Code schreiben, da Aufgaben nicht unbedingt in der Reihenfolge beendet werden, in der sie geschrieben wurden. Das ist keine schlechte Sache, weil wir keine Aufgabe haben wollen, die Fortsetzung des Programms zu blockieren.
Versprechen sind ein besseres Muster für das Schreiben von asynchronem Code. Sie beheben nicht nur das Durcheinander verschachtelter Callbacks, sondern behalten auch die Kontrolle über das Ergebnis einer Aufgabe innerhalb der Aufgabe. Wenn Sie die Kontrolle an eine andere Task übergeben, unabhängig davon, ob es sich um unseren eigenen Code oder eine API eines Drittanbieters handelt, ist der Code weniger zuverlässig. Schließlich erlauben uns async-Funktionen, unseren Code synchron zu schreiben, was viel intuitiver und verständlicher ist.