Ich habe über aufgeschobene und versprochene jQuery-Angebote gelesen und kann den Unterschied zwischen der Verwendung von .then()
& .done()
für erfolgreiche Rückrufe nicht erkennen. Ich weiß, dass Eric Hynds dies erwähnt .done()
und .success()
derselben Funktionalität zugeordnet ist, aber ich vermute , dass dies der Fall ist, .then()
da alle Rückrufe nach Abschluss eines erfolgreichen Vorgangs aufgerufen werden.
Kann mir bitte jemand die richtige Verwendung aufklären?
jquery
promise
jquery-deferred
screenm0nkey
quelle
quelle
Antworten:
Die an angehängten Rückrufe
done()
werden ausgelöst, wenn der Aufschub behoben ist. Die an angehängten Rückrufefail()
werden ausgelöst, wenn der Aufschub abgelehnt wird.Vor jQuery 1.8
then()
war nur syntaktischer Zucker:Ab 1,8,
then()
ist ein Alias fürpipe()
und gibt ein neues Versprechen finden Sie hier für weitere Informationen überpipe()
.success()
underror()
sind nur für dasjqXHR
Objekt verfügbar, das durch einen Aufruf an zurückgegeben wirdajax()
. Sie sind einfach Aliase fürdone()
undfail()
jeweils:Ist auch
done()
nicht auf einen einzelnen Rückruf beschränkt und filtert Nichtfunktionen heraus (obwohl es in Version 1.8 einen Fehler mit Zeichenfolgen gibt, der in 1.8.1 behoben werden sollte):Gleiches gilt für
fail()
.quelle
then
Ein neues Versprechen zurückzugeben war eine Schlüsselsache, die mir fehlte. Ich konnte nicht verstehen, warum eine Kette wie$.get(....).done(function(data1) { return $.get(...) }).done(function(data2) { ... })
mitdata2
undefiniert versagte ; Als ich dazu wechseltedone
,then
funktionierte es, weil ich wirklich Versprechen zusammenpfeifen wollte, anstatt mehr Handler an das ursprüngliche Versprechen anzuhängen.done
oderthen
? Warum?.then()
).Es gibt auch Unterschiede in der Art und Weise, wie Rückgabeergebnisse verarbeitet werden (die so genannte Verkettung verkettet
done
nicht, während Aufrufkettenthen
erzeugt werden).Die folgenden Ergebnisse werden protokolliert:
Während
wird folgendes bekommen:
---------- Update:
Übrigens. Ich habe vergessen zu erwähnen, dass das äußere Versprechen wartet, bis das innere Versprechen aufgelöst ist, wenn Sie ein Versprechen anstelle eines atomaren Wertes zurückgeben:
Auf diese Weise wird es sehr einfach, parallele oder sequentielle asynchrone Operationen zu erstellen, wie z.
Der obige Code gibt zwei http-Anforderungen parallel aus, wodurch die Anforderungen früher abgeschlossen werden, während die folgenden http-Anforderungen nacheinander ausgeführt werden, wodurch die Serverlast verringert wird
quelle
done
der nichts mit dem Ergebnis zu tun hat, wennthen
sich das Ergebnis ändert. Riesiger Punkt von den anderen imo verpasst.then
in 1.8done
undthen
aufgerufenen Ergebnissen resultieren.done
Beispiel. Wechseln Siethen
zupipe
Pre-1.8, um dasthen
Verhalten 1.8+ zu erhalten..done()
hat nur einen Rückruf und es ist der Erfolgsrückruf.then()
hat sowohl erfolgreiche als auch fehlgeschlagene Rückrufe.fail()
hat nur einen Fail-CallbackEs liegt also an Ihnen, was Sie tun müssen. Interessiert es Sie, ob es erfolgreich ist oder ob es fehlschlägt?
quelle
then()
stark vondone()
. Wiethen()
oft nur beim Erfolgsrückruf genannt wird, ist Ihr Punkt eher ein Detail als die Hauptsache, an die Sie sich erinnern / wissen sollten. (Ich kann nicht sagen, wie es vor jQuery 3.0 war.)deferred.done ()
Fügt Handler hinzu, die nur aufgerufen werden , wenn Deferred behoben ist . Sie können mehrere zurückzurufende Rückrufe hinzufügen.
Sie können auch oben so schreiben,
deferred.then ()
Fügt Handler hinzu, die aufgerufen werden sollen, wenn Zurückgestellt aufgelöst, abgelehnt oder noch ausgeführt wird .
quelle
then
verhält, wenn keinfail
Rückruf bereitgestellt wird - nämlich denfail
Fall überhaupt nicht zu erfassenEs gibt tatsächlich einen ziemlich kritischen Unterschied, da jQuery's Deferreds eine Implementierung von Promises sein sollen (und jQuery3.0 tatsächlich versucht, sie in die Spezifikation zu bringen).
Der Hauptunterschied zwischen erledigt / dann ist das
.done()
Gibt IMMER dieselben Promise / Wrapped-Werte zurück, mit denen es begonnen hat, unabhängig davon, was Sie tun oder was Sie zurückgeben..then()
Gibt immer ein NEUES Versprechen zurück, und Sie sind dafür verantwortlich, zu steuern, was dieses Versprechen basierend auf der Funktion, die Sie übergeben haben, zurückgegeben hat.Die Übersetzung von jQuery in native ES2015-Versprechungen
.done()
ähnelt der Implementierung einer "Tap" -Struktur um eine Funktion in einer Versprechenskette, indem sie einen Wert an eine Funktion übergibt , wenn sich die Kette im Zustand "Auflösen" befindet. Das Ergebnis dieser Funktion wirkt sich jedoch NICHT auf die Kette selbst aus.Diese werden beide 5 protokollieren, nicht 6.
Beachten Sie, dass ich done und doneWrap zum Protokollieren verwendet habe, nicht .then. Das liegt daran, dass die Funktionen console.log eigentlich nichts zurückgeben. Und was passiert, wenn Sie eine Funktion übergeben, die nichts zurückgibt?
Das wird protokollieren:
Was ist passiert? Wenn ich .then verwendet und ihm eine Funktion übergeben habe, die nichts zurückgegeben hat, war das implizite Ergebnis "undefined" ... was natürlich ein Versprechen [undefined] an die nächste then-Methode zurückgab, die undefined protokollierte. Der ursprüngliche Wert, mit dem wir begonnen haben, ging also im Grunde verloren.
.then()
ist im Kern eine Form der Funktionszusammensetzung: Das Ergebnis jedes Schritts wird im nächsten Schritt als Argument für die Funktion verwendet. Aus diesem Grund wird .done am besten als "Tippen" betrachtet -> es ist nicht Teil der Komposition, sondern nur etwas, das einen Blick auf den Wert in einem bestimmten Schritt wirft und eine Funktion mit diesem Wert ausführt, sich aber nicht wirklich ändert die Komposition in irgendeiner Weise.Dies ist ein ziemlich grundlegender Unterschied, und es gibt wahrscheinlich einen guten Grund, warum native Promises keine .done-Methode selbst implementiert haben. Wir müssen uns nicht damit befassen, warum es keine .fail-Methode gibt, da dies noch komplizierter ist (nämlich .fail / .catch sind KEINE Spiegel von .done / .then -> -Funktionen in .catch, die keine bloßen Werte zurückgeben "bleib" abgelehnt wie die an .then, sie beschließen!)
quelle
then()
bedeutet immer, dass es in jedem Fall aufgerufen wird. Die übergebenen Parameter sind jedoch in verschiedenen jQuery-Versionen unterschiedlich.Vor jQuery 1.8 ist
then()
gleichdone().fail()
. Alle Rückruffunktionen haben dieselben Parameter.Ab jQuery 1.8
then()
ein neues Versprechen zurückgegeben. Wenn es einen Wert zurückgibt, wird es an die nächste Rückruffunktion übergeben.Sehen wir uns das folgende Beispiel an:
Vor jQuery 1.8 sollte die Antwort lauten
Alles
result
dauert 3. Undthen()
Funktion übergibt immer das gleiche zurückgestellte Objekt an die nächste Funktion.Ab jQuery 1.8 sollte das Ergebnis jedoch Folgendes sein:
Da die erste
then()
Funktion ein neues Versprechen zurückgibt und der Wert 7 (und dies ist der einzige Parameter, der weitergegeben wird) an die nächste übergeben wirddone()
, wird der zweitedone()
geschriebenresult = 7
. Die zweitethen()
nimmt 7 als Wert vona
und nimmtundefined
als Wert vonb
, so dass die zweitethen()
ein neues Versprechen mit dem Parameter NaN zurückgibt und die letztedone()
NaN als Ergebnis druckt.quelle
jQuery.Deferred()
mehrere Werte empfangen kann, die es ordnungsgemäß an den ersten weitergibt.then()
. - Ein wenig seltsam ... da jede Folge.then()
dies nicht kann. (Die ausgewählte Schnittstelle überreturn
kann nur einen Wert zurückgeben.) Das native JavascriptPromise
macht das nicht. (Was konsequenter ist, um ehrlich zu sein.)Es gibt eine sehr einfache mentale Zuordnung als Antwort, die in den anderen Antworten etwas schwer zu finden war:
done
Gerätetap
wie in Bluebird Promisesthen
implementiertthen
wie in ES6 Promisesquelle
Benutz nur
.then()
Dies sind die Nachteile von
.done()
resolve()
(alle.done()
Handler werden synchron ausgeführt)resolve()
möglicherweise eine Ausnahme von registrierten.done()
Handlern (!).done()
halben Tötung der aufgeschobenen:.done()
Handler werden stillschweigend übersprungenIch dachte vorübergehend, dass dies
.then(oneArgOnly)
immer erforderlich ist,.catch()
damit keine Ausnahme stillschweigend ignoriert wird, aber das stimmt nicht mehr: Dasunhandledrejection
Ereignis protokolliert nicht behandelte.then()
Ausnahmen auf der Konsole (standardmäßig). Sehr vernünftig! Kein Grund mehr zu verwenden.done()
.Beweis
Das folgende Codefragment zeigt, dass:
.done()
Handler werden zum Zeitpunkt von als synchron bezeichnetresolve()
.done()
beeinflusstresolve()
Anruferresolve()
.done()
Auflösung.then()
hat keines dieser Problemeunhandledrejection
is scheint)Übrigens können Ausnahmen von
.done()
nicht richtig abgefangen werden: Aufgrund des synchronen Musters von.done()
wird der Fehler entweder an der Stelle.resolve()
(möglicherweise Bibliothekscode!) Oder beim.done()
Aufruf ausgelöst, der den Täter anhängt, wenn die Zurückstellung bereits behoben ist.quelle
done
das nicht ausgeführt wird, wenn eine vorherige Ausführung eine Ausnahme hat. Aber warum sollte es stillschweigend ignoriert werden? Ich meine, es ist eine Ausnahme aufgetreten. Warum sagen Sie, dass es still ist? 2) Ich verachte dasDeferred
Objekt, weil seine API sehr, sehr schlecht gemacht ist. Es ist zu komplex und verwirrend. Ihr Code hier hilft auch nicht, Ihren Standpunkt zu beweisen, und er hat zu viel unnötige Komplexität für das, was Sie zu beweisen versuchen. 3) Warum werden diedone
at Index 2, 4 und 6 vor dem 2. durchgeführtthen
?.then()
werden aufgerufen, Ausnahme (in diesen Handlern) ausgelöst oder nicht. Aber Zugabe / verbleibende.done()
Pause.Ab jQuery 3.0 gibt es noch einen entscheidenden Unterschied, der leicht zu unerwartetem Verhalten führen kann und in früheren Antworten nicht erwähnt wurde:
Betrachten Sie den folgenden Code:
Dies wird Folgendes ausgeben:
Nun ersetzen
done()
durchthen()
im gleichen Schnipsel:Ausgabe ist jetzt:
Bei sofort aufgelösten Verzögerungen wird die übergebene Funktion
done()
immer synchron aufgerufen, während jedes übergebene Argumentthen()
asynchron aufgerufen wird.Dies unterscheidet sich von früheren jQuery-Versionen, bei denen beide Rückrufe synchron aufgerufen werden, wie im Upgrade-Handbuch erwähnt :
quelle
.done()
Beendet die Versprechenskette und stellt sicher, dass nichts anderes weitere Schritte anhängen kann. Dies bedeutet, dass die Implementierung des jQuery-Versprechens jede nicht behandelte Ausnahme auslösen kann, da niemand damit umgehen kann.fail()
.In der Praxis sollten Sie verwenden, wenn Sie nicht vorhaben, einem Versprechen weitere Schritte beizufügen
.done()
. Weitere Einzelheiten erfahren Sie, warum Versprechungen gemacht werden müssenquelle
.done()
keine abschließende Rolle spielt. In der Dokumentation heißt es: "Da deferred.done () das zurückgestellte Objekt zurückgibt, können andere Methoden des zurückgestellten Objekts an dieses verkettet werden, einschließlich zusätzlicher .done () -Methoden.".fail()
wird nicht erwähnt, aber das könnte auch verkettet werden.