In diesem Artikel wird hauptsächlich die Verwendung von Versprechen populär.
JavaScript hat seit langer Zeit in Form von Rückrufen immer asynchron behandelt, und der Rückrufmechanismus im Bereich der Front-End-Entwicklung ist fast tief in den Herzen der Menschen verwurzelt. Beim Entwerfen von APIs, unabhängig davon, ob es sich um einen Browserhersteller, SDK -Entwickler oder Autor verschiedener Bibliothek handelt, folgen sie im Grunde genommen der Rückrufroutine.
In den letzten Jahren wurde mit der allmählichen Reife des JavaScript -Entwicklungsmodells die CommonJS -Spezifikation geboren, einschließlich des Vorschlags der Versprechenspezifikation. Das Versprechen hat das Schreiben der asynchronen JS -Programmierung vollständig verändert und asynchrone Programmieren sehr leicht zu verstehen.
Im Rückrufmodell gehen wir davon aus, dass eine asynchrone Warteschlange ausgeführt werden muss, und der Code kann so aussehen:
loadImg ('A.JPG', function () {loadImg ('b.jpg', function () {loadImg ('c.jpg', function () {console.log ('alle done!');});});});Dies ist es, was wir oft Pyramide zurückrufen. Wenn es viele asynchrone Aufgaben gibt, ist die Aufrechterhaltung einer großen Anzahl von Rückernständen eine Katastrophe. Heutzutage ist Node.js sehr beliebt. Es scheint, dass viele Teams es verwenden wollen, um etwas zu machen, um mit der "Mode" auszukommen. Sobald sie mit einem Betriebs- und Wartungsklassenkameraden chatten, planten sie auch, Node.js zu verwenden, um etwas zu tun, aber wenn sie an die Rückrufebenen von JS denken, werden sie entmutigt.
Ok, der Unsinn ist vorbei, lass uns zum Thema kommen.
Versprechen kann mit allen vertraut sein, da die Versprechenspezifikation lange Zeit veröffentlicht wurde und das Versprechen in ES6 aufgenommen wurde, und die höheren Versionen von Chrome- und Firefox -Browsern haben Versprechen nativ implementiert, aber es gibt heutzutage weniger APIs als die beliebte Verheißungsklassenbibliothek.
Das sogenannte Versprechen kann buchstäblich als "Versprechen" verstanden werden, was bedeutet, dass A angerufen B, B ein "Versprechen" an a zurückgibt, und dann kann A beim Schreiben des Plans ein "Versprechen" zurückgeben, und dann kann A beim Schreiben des Plans das Ergebnis zurückgeben. Im Gegenteil, wenn B aus irgendeinem Grund nicht das gewünschte Ergebnis erzielt, führt A das Notfallplan S2 aus, so dass alle potenziellen Risiken innerhalb von A's Controllable Range liegen.
Der obige Satz wird in Code übersetzt, ähnlich wie:
var resb = b (); var runa = function () {resb.then (execs1, execs2);}; runa ();Wenn man sich nur die obige Codezeile ansieht, scheint es nichts Besonderes zu geben. Aber die Realität mag viel komplizierter sein als diese. Um eine Sache zu erreichen, kann A auf die Reaktion von mehr als einer Person B. Die endgültige Übersetzung in den Code könnte so aussehen:
var resb = b (); var resside = c (); ... var runa = function () {reqb .then (resc, execs2) .then (resd, execs3) .then (resse, execs4) ... .then (execs1);}; runa ();Hier werden unterschiedliche Verarbeitungsmechanismen verwendet, wenn jede nachgefragte antwortete, die nicht den Erwartungen entsprechen. Tatsächlich erfordert die Versprechenspezifikation dies nicht, und Sie können sogar nichts tun (d. H. Nicht in den zweiten Parameter von dann) oder sie einheitlich umgehen.
OK, lasst uns die Versprechen/A+ -Spezipationen kennenlernen:
then Methode implementieren (es kann sagen, dass dann der Kern des Versprechens ist) und dann ein Versprechen zurückgeben muss. Dann kann das gleiche Versprechen mehrmals aufgerufen werden, und die Ausführungsreihenfolge der Rückrufe stimmt mit der Reihenfolge überein, wenn sie definiert sindWie Sie sehen können, gibt es in der Versprechenspezifikation nicht viel Inhalt, sodass Sie versuchen können, das folgende Versprechen selbst zu implementieren.
Das Folgende ist eine einfache Implementierung eines Versprechens, auf das ich auf viele Versprechensbibliotheken verwiesen habe. Bitte wechseln Sie im Code zu Promisea.
Eine kurze Analyse der Ideen:
Das Konstruktor -Versprechen akzeptiert einen resolver , der als asynchrone Aufgabe verstanden werden kann. Der Resolver akzeptiert zwei Parameter, einer ist ein Rückruf, wenn er erfolgreich ist, und der andere ist ein Rückruf, wenn es ausfällt. Diese beiden Parameter entsprechen den Parametern, die damals übergeben werden.
Die zweite ist die Implementierung von damals. Da das Versprechen erfordert, dass dann ein Versprechen zurückgegeben werden muss, wird ein neues Versprechen generiert, wenn er dann aufgerufen wird, das _next des aktuellen Versprechens aufgehängt wird. Mehrere Anrufe desselben Versprechens geben nur den zuvor generierten _next zurück.
Da die beiden von der damaligen Methode akzeptierten Parameter optional sind und der Typ keine Einschränkung gibt, kann es eine Funktion, ein bestimmter Wert oder ein anderes Versprechen sein. Hier ist die spezifische Implementierung von dann:
Promise.Prototype.Then = Funktion (Resolve, ablehnen) {var next = this._next || (this._Next = drequent ()); var status = this.status; var x; if ('anhängig' === Status) {isfn (Resolve) && this._resolves.push (Resolve); isfn (abgelehnt) && this._rejects.push (ablehnen); Als nächstes zurückkehren; } if ('aufgelöst' === Status) {if (! isfn (Resolve)) {next.resolve (Resolve); } else {try {x = Resolve (this.Value); Resolvex (Weiter, x); } catch (e) {this.Reject (e); }} zurückkehren als nächstes; } if ('abgelehnt' === Status) {if (! isfn (reject)) {next.Reject (ablehnen); } else {try {x = reject (this.reason); Resolvex (Weiter, x); } catch (e) {this.Reject (e); }} zurückkehren als nächstes; }};Hier hat dann die Implementierung anderer Versprechen -Klassenbibliotheken vereinfacht, und die Implementierung ist viel komplexer als diese und hat auch mehr Funktionen. Beispielsweise gibt es einen dritten Parameter - Benachrichtigung, der den aktuellen Fortschritt des Versprechens anzeigt, was beim Hochladen von Entwurfsdateien usw. sehr nützlich ist. Die Verarbeitung verschiedener Parameter von dann ist der komplizierteste Teil. Interessierte Schüler können sich auf die Implementierung anderer Arten von Versprechensbibliotheken beziehen.
Auf der Grundlage von damals sollten mindestens zwei Methoden erforderlich sein, nämlich die Umwandlung des Zustands des Versprechens von anhängig in die gelösten oder abgelehnten Versprechen und die entsprechenden Rückruf -Warteschlangen, nämlich resolve() und reject() () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () () Methoden.
Zu diesem Zeitpunkt wurde ein einfaches Versprechen entworfen. Im Folgenden finden Sie einfache Implementierungen der folgenden beiden versprochenen Funktionen:
Funktion Sleep (ms) {return function (v) {var p = drequent (); setTimeout (function () {p.resolve (v);}, ms); Rückkehr p; };}; function getImg (url) {var p = drequent (); var img = new Image (); img.onload = function () {p.resolve (this); }; img.onError = function (err) {P.Reject (err); }; img.url = url; return p;}; Da der Versprechungskonstruktor eine asynchrone Aufgabe als Parameter akzeptiert, kann getImg auch so genannt werden:
Funktion getImg (url) {return verspricht (Funktion (Resolve, ablehnen) {var img = new Image (); img.onload = Funktion () {Resolve (this);}; img.onerror = Funktion (err) {reject (err.Als nächstes (der Moment des Zeugens des Wunders) besteht angenommen, dass es eine BT -Anforderung gibt, dies zu implementieren: Holen Sie sich eine JSON -Konfiguration asynchron, analysieren Sie die JSON -Daten und laden Sie die Bilder in die Bilder und laden Sie die Bilder nacheinander und geben Sie einen Ladeeffekt, wenn kein Bild geladen wird.
Funktion addimg (img) {$ ('#list'). find ('> li: last-Kind'). html (''). append (img); getData ('map.json') .then (function (data) {$ ('h4'). Promise.Resolve ());Der Schlaf hier wird nur hinzugefügt, um den Effekt zu sehen. Sie können klicken, um die Demo anzuzeigen! Natürlich kann das Beispiel von Node.js hier angezeigt werden.
Hier gibt die statische Methode des Promise.resolve(v) gibt einfach ein Versprechen mit V als positives Ergebnis zurück. V kann nicht eingegeben werden oder es kann eine Funktion oder ein Objekt oder eine Funktion sein, die then eine Methode (d. H. Dann).
Ähnliche statische Methoden sind Promise.cast(promise) , das ein Versprechen mit Versprechen als positives Ergebnis erzeugt;
Promise.reject(reason) erzeugt ein Versprechen mit Vernunft als negatives Ergebnis.
Unsere tatsächlichen Nutzungsszenarien sind möglicherweise sehr komplex und erfordern häufig mehrere asynchrone Aufgaben, um interspürlich, parallel oder seriell ausgeführt zu werden. Zu diesem Zeitpunkt können Sie verschiedene Erweiterungen versprechen, z. B. das Umsetzung Promise.all() , die Annahme der Versprechenswarteschlangen und das Warten darauf, dass sie abgeschlossen sind, bevor Sie fortfahren, und zum Beispiel Promise.any() , wenn sich eines der Versprechen im Abschlussstatus befindet, wird die nächste Operation ausgelöst.
Sie können diesen Artikel in HTML5Rocks JavaScript -Versprechen beziehen. Derzeit haben fortschrittliche Browser wie Chrome und Firefox integrierte Versprechensobjekte, die mehr Operation Schnittstellen wie Promise.all() bereitstellen, die das Bestehen eines Versprechens-Arrays unterstützt und dann ausgeführt wird, wenn alle Versprechen abgeschlossen sind. Es gibt auch eine freundlichere und leistungsstarke Ausnahmeregelung, die ausreichen sollte, um mit der täglichen asynchronen Programmierung umzugehen.
Die beliebtesten JS -Bibliotheken haben heute das Versprechen für unterschiedliche Abschlüsse wie Dojo, JQuery, Zepto, When.js, Q usw. implementiert, aber die meisten exponierten Objekte Deferred . Implementieren Sie als Beispiel JQuery (Zepto ähnlich) und implementieren Sie das obige getImg() :
Funktion getImg (url) {var def = $ .deferred (); var img = new Image (); img.onload = function () {def.resolve (this); }; img.onerror = function (err) {def.Reject (err); }; img.src = url; return def.Promise ();}; In JQuery kehren natürlich viele Operationen zurück oder versprechen, wie animate und ajax :
// ajax $ .ajax (opazität ': 0}, 1000) .Promise () .then (function () {console.log (' Done ');}); // Ajax $ .ajax (Optionen) .Then (Erfolg, Fail, $. $ .ajax (options2)) .then (function () {console.log ('alle erledigt.');}, function () {console.Error ('da etwas falsch.');}); JQuery implementiert auch done() und fail() , die tatsächlich Verknüpfungen der damaligen Methode sind.
Um Versprechen zu bewältigen, implementiert JQuery $.when() -Methode, und ihre Verwendung ähnelt dem Promise.all() .
Für andere Klassenbibliotheken ist es hier erwähnenswert, dass, wenn Aus Platzbeschränkungen werden wir es nicht mehr erweitern.
Wir sehen, dass die Nutzung sehr einfach und der Organisationscode sehr klar ist, egal wie komplex die Implementierung von Versprechen ist. Von nun an ist es nicht erforderlich, durch Rückrufe gefoltert zu werden.
Schließlich ist das Versprechen so elegant! Aber Versprechen löst nur das Problem der tiefen Verschachtelung von Rückrufen. Es ist der Generator, der JavaScript Asynchronous -Programmierung wirklich vereinfacht. Auf der Seite node.js wird empfohlen, den Generator in Betracht zu ziehen.
Nächster Artikel, Studiengenerator.
GitHub Original Text: https://github.com/chemdemo/chemdemo.github.io/issues/6