521 Stimmen

jQuery Deferreds und Versprechen - .then() vs .done()

Ich habe über jQuery deferreds und Versprechen gelesen und ich kann nicht sehen, den Unterschied zwischen mit .then() & .done() für erfolgreiche Rückrufe. Ich weiß Eric Hynds erwähnt, dass .done() y .success() auf dieselbe Funktionalität abbilden, aber ich vermute, dass dies auch für .then() da alle Rückrufe bei Abschluss eines erfolgreichen Vorgangs aufgerufen werden.

Kann mich bitte jemand über die korrekte Verwendung aufklären?

15 Stimmen

Bitte beachten Sie, dass JQuery 3.0, das im Juni 2016 veröffentlicht wurde, die erste Version war, die mit der Promises/A+ und ES2015 Promises-Spezifikation konform war. Die Implementierung davor hatte Inkompatibilitäten mit dem, was Promises liefern sollten.

0 Stimmen

I aktualisiert meine Antwort mit einer verbesserten Empfehlung, was wann zu verwenden ist.

600voto

Julian Aubourg Punkte 11186

Die Rückrufe, die mit done() wird ausgelöst, wenn die Verzögerung aufgelöst wird. Die Callbacks, die an fail() wird ausgelöst, wenn die Zurückstellung abgelehnt wird.

Vor jQuery 1.8, then() war nur syntaktischer Zucker:

promise.then( doneCallback, failCallback )
// was equivalent to
promise.done( doneCallback ).fail( failCallback )

Ab dem 1.8, then() ist ein Alias für pipe() und gibt ein neues Versprechen zurück, siehe aquí für weitere Informationen über pipe() .

success() y error() sind nur auf der Website jqXHR Objekt, das durch einen Aufruf von ajax() . Sie sind einfache Aliasnamen für done() y fail() beziehungsweise:

jqXHR.done === jqXHR.success
jqXHR.fail === jqXHR.error

Auch, done() ist nicht auf einen einzigen Callback beschränkt und filtert Nicht-Funktionen heraus (allerdings gibt es in Version 1.8 einen Fehler mit Strings, der in 1.8.1 behoben sein sollte):

// this will add fn1 to 7 to the deferred's internal callback list
// (true, 56 and "omg" will be ignored)
promise.done( fn1, fn2, true, [ fn3, [ fn4, 56, fn5 ], "omg", fn6 ], fn7 );

Das Gleiche gilt für fail() .

10 Stimmen

then Die Rückgabe eines neuen Versprechens war ein wichtiger Punkt, der mir fehlte. Ich konnte nicht verstehen, warum eine Kette wie $.get(....).done(function(data1) { return $.get(...) }).done(function(data2) { ... }) scheiterte mit data2 undefiniert; als ich die done a then es funktionierte, denn ich war wirklich wollen, Rohr Versprechen zusammen, anstatt mehr Handler an das ursprüngliche Versprechen anhängen.

5 Stimmen

JQuery 3.0 ist die erste Version, die mit Promises/A+ und der ES2015-Spezifikation konform ist.

4 Stimmen

Ich verstehe immer noch nicht, warum ich das eine dem anderen vorziehen sollte. Wenn ich einen Ajax-Aufruf tätige und warten muss, bis der Aufruf vollständig abgeschlossen ist (d. h. die Antwort wird vom Server zurückgegeben), bevor ich einen weiteren Ajax-Aufruf tätige, verwende ich done o then ? Und warum?

441voto

Lu4 Punkte 14385

Es gibt auch einen Unterschied in der Art und Weise, wie die Rückgabeergebnisse verarbeitet werden (Verkettung genannt), done nicht verkettet, während then erzeugt Aufrufketten)

promise.then(function (x) { // Suppose promise returns "abc"
    console.log(x);
    return 123;
}).then(function (x){
    console.log(x);
}).then(function (x){
    console.log(x)
})

Die folgenden Ergebnisse werden protokolliert:

abc
123
undefined

Während

promise.done(function (x) { // Suppose promise returns "abc"
    console.log(x);
    return 123;
}).done(function (x){
    console.log(x);
}).done(function (x){
    console.log(x)
})

erhalten Sie Folgendes:

abc
abc
abc

---------- Update:

Btw. Ich vergaß zu erwähnen, wenn Sie ein Versprechen anstelle von atomaren Typ Wert zurückgeben, wird das äußere Versprechen warten, bis innere Versprechen auflöst:

promise.then(function (x) { // Suppose promise returns "abc"
    console.log(x);
    return $http.get('/some/data').then(function (result) {
        console.log(result); // suppose result === "xyz"
        return result;
    });
}).then(function (result){
    console.log(result); // result === xyz
}).then(function (und){
    console.log(und) // und === undefined, because of absence of return statement in above then
})

Auf diese Weise wird es sehr einfach, parallele oder sequentielle asynchrone Operationen wie z.B.:

// Parallel http requests
promise.then(function (x) { // Suppose promise returns "abc"
    console.log(x);

    var promise1 = $http.get('/some/data?value=xyz').then(function (result) {
        console.log(result); // suppose result === "xyz"
        return result;
    });

    var promise2 = $http.get('/some/data?value=uvm').then(function (result) {
        console.log(result); // suppose result === "uvm"
        return result;
    });

    return promise1.then(function (result1) {
        return promise2.then(function (result2) {
           return { result1: result1, result2: result2; }
        });
    });
}).then(function (result){
    console.log(result); // result === { result1: 'xyz', result2: 'uvm' }
}).then(function (und){
    console.log(und) // und === undefined, because of absence of return statement in above then
})

Der obige Code gibt zwei http-Anfragen parallel aus, so dass die Anfragen schneller abgeschlossen werden, während unten die http-Anfragen sequentiell ausgeführt werden, wodurch die Serverlast verringert wird

// Sequential http requests
promise.then(function (x) { // Suppose promise returns "abc"
    console.log(x);

    return $http.get('/some/data?value=xyz').then(function (result1) {
        console.log(result1); // suppose result1 === "xyz"
        return $http.get('/some/data?value=uvm').then(function (result2) {
            console.log(result2); // suppose result2 === "uvm"
            return { result1: result1, result2: result2; };
        });
    });
}).then(function (result){
    console.log(result); // result === { result1: 'xyz', result2: 'uvm' }
}).then(function (und){
    console.log(und) // und === undefined, because of absence of return statement in above then
})

131 Stimmen

+1 für die Vorstellung, dass done ändert nichts an dem Ergebnis, wenn then ändert das Ergebnis. Ein wichtiger Punkt, den die anderen meiner Meinung nach übersehen haben.

9 Stimmen

Es ist wahrscheinlich erwähnenswert, welche Version von jQuery dies gilt, da das Verhalten von then geändert in 1.8

4 Stimmen

+1 Direkt auf den Punkt gebracht. Ich habe eine lauffähiges Beispiel wenn jemand sehen will, welche Ketten mit gemischten done y then Anrufe führen zu.

60voto

Marino Šimić Punkte 7256

.done() hat nur einen Callback und das ist der Erfolgs-Callback

.then() hat sowohl Erfolgs- als auch Fehlerrückrufe

.fail() hat nur einen Fail-Callback

Es liegt also an Ihnen, was Sie tun müssen... ist es Ihnen egal, ob es gelingt oder nicht?

18 Stimmen

Sie vergessen zu erwähnen, dass das "then" Aufrufketten erzeugt. Siehe die Antwort von Lu4.

0 Stimmen

Ihre Antwort ist von 2011... Heutzutage machen ihre Rückgabewerte then() ganz anders als done() . En then() oft nur mit dem Erfolgs-Callback aufgerufen wird, ist Ihr Punkt eher ein Detail als die Hauptsache, die es zu beachten gilt. (Kann nicht sagen, wie es vor jQuery 3.0 war.)

16voto

Nipuna Punkte 6086

Deferred.done()

fügt aufzurufende Handler hinzu nur wenn Deferred aufgelöst wird . Sie können mehrere aufzurufende Rückrufe hinzufügen.

var url = 'http://jsonplaceholder.typicode.com/posts/1';
$.ajax(url).done(doneCallback);

function doneCallback(result) {
    console.log('Result 1 ' + result);
}

Sie können auch so darüber schreiben,

function ajaxCall() {
    var url = 'http://jsonplaceholder.typicode.com/posts/1';
    return $.ajax(url);
}

$.when(ajaxCall()).then(doneCallback, failCallback);

deferred.then()

fügt aufzurufende Handler hinzu wenn Aufgeschoben ist aufgehoben, abgelehnt oder noch in Bearbeitung .

var url = 'http://jsonplaceholder.typicode.com/posts/1';
$.ajax(url).then(doneCallback, failCallback);

function doneCallback(result) {
    console.log('Result ' + result);
}

function failCallback(result) {
    console.log('Result ' + result);
}

0 Stimmen

Aus Ihrem Beitrag geht nicht hervor, wie then verhält sich, wenn keine fail Callback vorgesehen ist - nämlich nicht das Erfassen der fail Fall überhaupt

0 Stimmen

Der Fehlerfall löst eine Ausnahme aus, die von der obersten Ebene des Programms abgefangen werden kann. Sie können die Ausnahme auch in der JavaScript-Konsole sehen.

11voto

Dtipson Punkte 1475

Es gibt tatsächlich einen ziemlich kritischen Unterschied, insofern als jQuery's Deferreds gemeint sind, eine Implementierungen von Promises (und jQuery3.0 tatsächlich versucht, sie in spec zu bringen).

Der Hauptunterschied zwischen done/then besteht darin, dass

  • .done() gibt IMMER die gleichen Versprechen/eingeschlossenen 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 kontrollieren, was dieses Versprechen ist, basierend auf dem, was die Funktion, die Sie übergeben haben, zurückgegeben hat.

Übersetzt von jQuery in native ES2015 Promises, .done() ist so etwas wie die Implementierung einer "Tap"-Struktur um eine Funktion in einer Promise-Kette, die, wenn sich die Kette im Zustand "resolve" befindet, einen Wert an eine Funktion übergibt... aber das Ergebnis dieser Funktion wirkt sich 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 mit 5, nicht mit 6 Punkten bewertet.

Beachten Sie, dass ich done und doneWrap für die Protokollierung verwendet habe, nicht .then. Das liegt daran, dass die console.log-Funktionen eigentlich nichts zurückgeben. Und was passiert, wenn Sie .then 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 protokolliert:

5

undefiniert

Was ist passiert? Wenn ich .then verwendete und eine Funktion übergab, die nichts zurückgab, war das implizite Ergebnis "undefined"... was natürlich ein Promise[undefined] an die nächste then-Methode zurückgab, die undefined protokollierte. Der ursprüngliche Wert, mit dem wir begonnen hatten, war also im Grunde verloren.

.then() ist im Grunde eine Form der Funktionskomposition: Das Ergebnis eines jeden Schritts wird als Argument für die Funktion im nächsten Schritt verwendet. Deshalb kann man sich .done am besten als "Tap" vorstellen -> es ist nicht wirklich Teil der Komposition, sondern nur etwas, das einen Blick auf den Wert bei einem bestimmten Schritt wirft und eine Funktion mit diesem Wert ausführt, aber die Komposition in keiner Weise verändert.

Dies ist ein ziemlich grundlegender Unterschied, und es gibt wahrscheinlich einen guten Grund, warum native Promises nicht selbst eine .done-Methode implementiert haben. Wir müssen gar nicht erst darauf eingehen, warum es keine .fail-Methode gibt, denn das ist noch komplizierter (nämlich sind .fail/.catch KEINE Spiegel von .done/.then -> Funktionen in .catch, die nackte Werte zurückgeben, "bleiben" nicht abgelehnt wie die an .then übergebenen, sie lösen sich auf!)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X