Vorwort
Ein Versprechensobjekt kann als Operation verstanden werden, die durchgeführt werden soll (häufig für asynchrone Operationen verwendet). Nach der Verwendung des Versprechensobjekts kann der Code in einem Kettenanruf organisiert werden, um den Code intuitiver zu gestalten. Darüber hinaus kann die Existenz einer solchen Methode als Versprechen einfach gemacht werden, mehrere Operationen gleichzeitig auszuführen.
Der Aufstieg des Versprechens ist, dass bei asynchronen Methodenaufrufe Callback -Funktionen häufig nacheinander auftreten. Diese Situation hat zur Entstehung von Callback -Pyramidenproblemen geführt. Der Code ist nicht nur schwierig und nicht schön zu schreiben, sondern macht es auch für Menschen, die den Code lesen, schwierig, zu verstehen, wann das Problem kompliziert ist.
Als Beispiel:
db.save (data, function (data) {// etwas tun ... db.save (Data1, Funktion (Daten) {// etwas tun ... db.save (data2, function (data) {// etwas tun ... Done (Data3); // Daten zurückgeben})});}); Angenommen, es gibt eine Datenbankspeicheroperation, und eine Anforderung erfordert, dass die Daten dreimal in drei Tabellen gespeichert werden. Dann ähnelt unser Code dem obigen Code. Was soll ich tun, wenn es zu diesem Zeitpunkt ein Problem in der zweiten db.save gibt? Basierend auf dieser Überlegung müssen wir Logik wie try...catch . Dies ist die Quelle des gesamten Bösen, und es ist auch ein Punkt, dass der Knoten am Anfang weithin kritisiert wurde.
Ein weiterer Nachteil ist, dass die Annahme, dass es keine Abhängigkeit von Front und Back zwischen unseren drei Paraden gibt, noch darauf warten müssen, dass die vorherige Funktion vor dem nächsten Schritt ausgeführt wird, und die drei Paraden können nicht parallelisiert werden, und geben dann das nach den drei Paraden erforderliche Ergebnis zurück. (Oder es erfordert Fähigkeiten, um es umzusetzen)
Als ich anfing, mich zum ersten Mal in den Knoten zu verwickeln, schrieb ich viele Höllen wie diese.
Später, weil ich immer noch mehr Front-End-Code schrieb, kam ich mit ES6 in Kontakt und fand ein leistungsstarkes Tool zur Lösung des Rückrufabhäufers.
Lange vor dem ES6 -Versprechen, Q, When.js, Bluebird und anderen Bibliotheken hatten bereits ihre eigenen Versprechensräder auf der Grundlage des Versprechensstandards (siehe Versprechen/A+) gebaut.
(Ich habe einen Artikel gelesen und ich denke, es macht Sinn. Es heißt, dass Sie keine integrierten nativen Objekte erweitern sollten. Dieser Ansatz kann nicht zukunftsorientiert werden. Hier ist also ein Tipp: Seien Sie vorsichtig, wenn Sie Bibliotheken verwenden, die ein natives Versprechen erweitern.)
Hier wird nur ein natives Versprechen diskutiert.
ES6 Versprechen
Status des Objekts versprechen
Bevor Sie das Versprechen im Detail erläutern, nehmen wir zunächst eine Theorie:
Versprechen/A+ Spezifikation sieht vor, dass das Versprechensobjekt eine endliche Zustandsmaschine ist.
Es hat drei Staaten:
1. pending (Ausführung)
2. fulfilled (erfolgreich)
3 reject
Wenn pending der Anfangszustand ist, fulfilled und rejected sind die Endzustände (der Endzustand zeigt an, dass der Lebenszyklus des Versprechens beendet ist).
Die staatliche Übergangsbeziehung lautet:
anhängig-> erfüllt, ausstehend-> abgelehnt.
Verschiedene Ereignisse werden als staatliche Übergänge ausgelöst (wie erfolgreiche Ausführungsereignisse, fehlgeschlagene Ausführungsereignisse usw.).
Versprechensform
Versprechen sieht so aus:
var varly = new Promise (Funktion func (Resolve, Ablehnung) {// etwas tun, vielleicht asynchronen, wenn (Erfolg) {return Resolve (data);} else {return reject (data);}}); Versprechen.Then (Funktion (Daten) {// etwas ... z.Das variable Versprechen hier ist eine Instanz des Versprechensobjekts.
Wenn das Versprechensobjekt erstellt wird, wird die Logik in func -Funktion ausgeführt.
Wenn die Logik verarbeitet wird und keine Fehler vorliegen, übergibt der Rückruf resolve den Wert an einen besonderen Ort. Wo ist dieser besondere Ort? Das ist dann im folgenden Code. Wir verwenden die Rückruffunktion then , um das Ergebnis nach resolve zu verarbeiten. Zum Beispiel geben wir im obigen Code einfach den Wert für die Konsole aus. Wenn ein Fehler vorliegt, reject ihn in die zweite Rückruffunktion then ab, um den Fehler zu verarbeiten.
In Übereinstimmung mit der oben reject Theorie der endlichen Zustandsmaschine wissen wir, dass der Staat bei resolve Ausführung fulfilled Callback -Funktionscode im Promise -Konstruktor pending reject
Datenfluss versprechen
Das obige ist der erste Datenfluss des Versprechens.
Was lustig ist, ist, dass die then Methode des Versprechens immer noch ein Versprechensobjekt zurückgeben kann, damit wir den then verwenden können, um dieselbe Verarbeitung durchzuführen.
Die beiden Rückruffunktionen in der ersten bestimmen then welche Art von Versprechen das erste then zurückgibt.
Unter der Annahme, dass der erste Rückruf des ersten then kein Versprechensobjekt zurückgibt, ist der Anrufer des zweiten then immer noch das ursprüngliche Versprechensobjekt, außer dass sein Auflösungswert zum Rückgabewert der ersten Rückruffunktion in der ersten dann wird.
Unter der Annahme, dass die erste then die erste Rückruffunktion ein Versprechensobjekt zurückgibt, wird der zweite then Anrufer zu diesem neuen Versprechensobjekt, und der zweite wartet then auf das neue Versprechen, das den Rückruf auflöst oder ablehnt und ausführt.
Obwohl ich ein wenig verschont habe, habe ich das Gefühl, dass ich immer noch sehr klar bin. Haha ~
Wenn irgendwo ein Fehler auftritt, wird der Fehler an die zweite Rückruffunktion übergeben, die mit der zweiten Rückruffunktion then , um sie zu verarbeiten. Es ist zu verstehen, dass der Fehler nach hinten reject bis er verarbeitet wird.
Darüber hinaus verfügt das Promise -Objekt auch über einen Methode catch , der eine Rückruffunktion zum Umgang mit Fehlern akzeptiert.
Im Augenblick:
Promise.Catch (Funktion (Err) {// Die Err.} abwickeln)Unter der Annahme, dass die Behandlung von Fehlern ähnlich ist, kann diese Methode zentral und einheitlich Fehler umgehen. Andere dann erfordern Methoden keinen zweiten Rückruf ~
Kontrolle über gleichzeitige Versprechen
Promise hat eine "statische Methode" - Promise.all (Beachten Sie, dass es nicht verspricht.Prototypen). Diese Methode akzeptiert ein Element, das eine Reihe von Versprechensobjekten ist.
Diese Methode gibt auch ein Versprechensobjekt zurück. Wenn alle Versprechensobjekte im Array resolve werden, werden die resolve Werte als Array als resolve Wert des (Versprechensobjekts) des Rückgabewerts der Promise.all -Methode verwendet und können dann von der then Methode verarbeitet werden. Wenn ein Versprechen im Array reject wird, ist der reject der reject des Rückgabewerts Promise.all .
Ein sehr undurchsichtiger Punkt ist:
Die Reihenfolge resolve (wie oben erwähnt, ein Array), das von der ersten Rückruffunktion der then Methode empfangen wird, entspricht der Reihenfolge des Parameter -Arrays in Promise.all Alle und nicht in chronologischer Reihenfolge.
Es gibt auch eine ähnliche Methode wie Promise.all Alle Promise.race , die auch ein Array erhält, außer dass es nur den ersten Wert resolve .
Verwandeln Sie andere Objekte in Versprechenobjekte
Die Promise.resovle -Methode kann ein Versprechensobjekt als Parameter zurückgeben.
Es gibt zwei Situationen:
Unter der Annahme, dass es .then Methode des übergebenen Parameters gibt, wird das zurückgegebene Versprechensobjekt resolve Auflösungsstatus, und der resolve Wert ist das Objekt selbst.
Unter der Annahme, dass der übergebene Parameter eine then Methode hat (als thenable Objekt bezeichnet) wird der Typ dieses Objekts in Versprechen geändert, und seine then Methode wird Promise.prototype.then .
Ist Versprechen eine Lösung für asynchron?
Lassen Sie mich schließlich etwas sehr Wichtiges sagen: Die Funktion von Promise besteht darin, das Problem der Rückrufpyramiden zu lösen, und es spielt eigentlich keine große Rolle bei der Kontrolle des asynchronen Prozesses. Um wirklich Versprechen zu verwenden, um den asynchronen Prozess zu steuern, müssen wir auch die ES6 generator verwenden. (Zum Beispiel die Implementierung der CO -Bibliothek des TJ -Meisters).
ES7 wird jedoch eine fantastischere Lösung haben: async/await , das der CO ähnelt, aber native Unterstützung hat. Lassen Sie uns warten und sehen.
Zusammenfassen
In dem oben genannten dreht sich alles um das native Versprechen in JavaScript ES6. Ich hoffe, der Inhalt dieses Artikels wird für alle im Lernen von ES6 hilfreich sein. Wenn Sie Fragen haben, überlassen Sie bitte eine Nachricht, um zu kommunizieren.