Es 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.
const doneWrap = fn => x => { fn(x); return x };
Promise.resolve(5)
.then(doneWrap( x => x + 1))
.then(doneWrap(console.log.bind(console)));
$.Deferred().resolve(5)
.done(x => x + 1)
.done(console.log.bind(console));
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?
Promise.resolve(5)
.then(doneWrap( x => x + 1))
.then(console.log.bind(console))
.then(console.log.bind(console));
Das wird protokollieren:
5
nicht definiert
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!)