jQuery deferreds et de promesses.alors() vs fait()

j'ai lu à propos de jQuery deferreds and promises et je ne vois pas la différence entre l'utilisation de .then() et .done() pour les callbacks réussis. Je sais que Eric Hynds mentionne que .done() et .success() correspondent à la même fonctionnalité, mais je suppose qu'il en va de même pour .then() puisque toutes les callbacks sont invoquées à la fin d'une opération réussie.

est-ce que quelqu'un peut m'éclairer sur l'usage correct?

merci Beaucoup

421
demandé sur Bergi 2011-03-25 21:02:48

8 réponses

les callbacks attachés à done() seront désactivés lorsque le report est résolu. Les callbacks attachés à fail() seront désactivés lorsque le report est rejeté.

avant jQuery 1.8, then() était juste du sucre syntaxique:

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

à partir de 1.8, then() est un alias pour pipe() et retourne une nouvelle promesse, voir ici pour plus d'informations sur pipe() .

success() et error() ne sont disponibles que sur le jqXHR de l'objet renvoyé par un appel à ajax() . Il s'agit de simples Alias pour done() et fail() respectivement:

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

aussi, done() n'est pas limité à un seul rappel et filtrera les non-fonctions (bien qu'il y ait un bug avec des chaînes dans la version 1.8 qui devrait être corrigé dans 1.8.1):

// 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 );

idem pour fail() .

522
répondu Julian Aubourg 2017-05-23 12:26:27

il y a également une différence dans la façon dont les résultats de retour sont traités (son appelé enchaînement, done ne chaine pas tandis que then produit des chaînes d'appel)

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)
})

les résultats suivants seront enregistrés:

abc
123
undefined

alors que

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)
})

obtiendra ce qui suit:

abc
abc
abc

---------- mise à Jour:

Btw. J'ai oublié de mentionner, si vous retourner une promesse au lieu d'une valeur de type atomique, la promesse extérieure attendra que la promesse intérieure se résolve:

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
})

de cette façon, il devient très simple de composer des opérations asynchrones parallèles ou séquentielles telles que:

// 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
})

le code ci-dessus émet deux requêtes http en parallèle, ce qui rend les requêtes complètes plus tôt, alors qu'en dessous de ces requêtes http sont exécutées de manière séquentielle, réduisant ainsi la charge du serveur

// 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
})
367
répondu Lu4 2017-01-29 08:59:39

.done() n'a qu'une fonction de rappel et c'est le succès de rappel

.then() a à la fois le succès et l'échec des rappels

.fail() n'a pas de rappel

c'est donc à vous de décider ce que vous devez faire... ne vous vous souciez si il réussit ou échoue?

49
répondu Marino Šimić 2015-06-27 18:10:11

différé.fait le ()

, ajoute gestionnaires à être appelé uniquement lorsqu'ils sont Reportés est résolu . Vous pouvez ajouter plusieurs rappels à être appelé.

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

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

vous pouvez aussi écrire ci-dessus comme ceci,

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

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

différé.puis ()

ajoute handlers à appeler lorsque le Report est résolu, rejeté ou encore en cours .

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);
}
12
répondu Nipuna 2015-03-15 03:42:50

il y a en fait une différence assez critique, dans la mesure où les reports de jQuery sont censés être des implémentations de promesses (et jQuery3.0 tente en fait de les faire entrer dans le spec).

la principale différence entre done / then est que

  • .done() " retourne toujours les mêmes valeurs promises/emballées qu'au départ, peu importe ce que vous faites ou ce que vous retournez.
  • .then() retourne toujours un nouveau Promesse, et vous êtes en charge de contrôler ce que cette promesse est basée sur ce que la fonction que vous avez passé il retourné.

traduit de jQuery en promesses natives ES2015, .done() est une sorte de mise en œuvre d'une structure "tap" autour d'une fonction dans une chaîne Promise, en ce sens qu'elle passera une valeur à une fonction si la chaîne est dans l'état "resolve"... mais le résultat de cette fonction n'affectera pas la chaîne elle-même.

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));

les deux logeront 5, Pas 6.

notez que j'ai utilisé done et doneWrap pour faire de la journalisation, pas .puis. C'est parce que la console.les fonctions de journalisation ne renvoient rien. Et ce qui se passe si tu passes .ensuite, une fonction qui ne retourne rien?

Promise.resolve(5)
       .then(doneWrap( x => x + 1))
       .then(console.log.bind(console))
       .then(console.log.bind(console));

Qui sera journal:

5

Non défini

que s'est-il passé? Lorsque je l'ai utilisé .puis et lui a passé une fonction qui n'a rien retourné, son résultat implicite était"indéfini"... qui, bien sûr, renvoie une promesse [undefined] à la prochaine méthode then, qui se connecte undefined. Donc la valeur originale avec laquelle nous avons commencé a été pratiquement perdue.

.then() est, au fond, une forme de composition de fonctions: le résultat de chaque étape est utilisé comme argument de la fonction dans l'étape suivante. C'est pourquoi .fait est mieux considéré comme un "tap"-> il ne fait pas réellement partie de la composition, juste quelque chose qui jette un coup d'oeil à la valeur à une certaine étape et exécute une fonction à cette valeur, mais ne modifie pas réellement la composition en aucune façon.

il s'agit d'une différence assez fondamentale, et il y a probablement une bonne raison pour laquelle les promesses des Autochtones n'ont pas de .fait méthode mis en œuvre eux-mêmes. On n'a pas à se demander pourquoi il n'y en a pas .méthode d'échec, parce que c'est encore plus compliqué (à savoir,.échouer./catch ne sont pas des miroirs de .faire./puis>- fonctions de dans .attraper le retour à nu les valeurs ne sont pas "rester" rejeté comme ceux qui sont passés .alors, ils décident!)

6
répondu Dtipson 2016-06-01 02:51:51

then() signifie toujours qu'il sera appelé dans tous les cas. Mais les paramètres de passage sont différents dans les différentes versions de jQuery.

avant jQuery 1.8, then() égale done().fail() . Et toutes les fonctions de rappel partagent les mêmes paramètres.

mais à partir de jQuery 1.8, then() retourne une nouvelle promesse, et si elle a retourner une valeur, elle sera passée dans la fonction de rappel suivante.

let's voir l'exemple suivant:

var defer = jQuery.Deferred();

defer.done(function(a, b){
            return a + b;
}).done(function( result ) {
            console.log("result = " + result);
}).then(function( a, b ) {
            return a + b;
}).done(function( result ) {
            console.log("result = " + result);
}).then(function( a, b ) {
            return a + b;
}).done(function( result ) {
            console.log("result = " + result);
});

defer.resolve( 3, 4 );

avant jQuery 1.8, la réponse devrait être

result = 3
result = 3
result = 3

Tous result prend 3. Et la fonction then() passe toujours le même objet différé à la fonction suivante.

mais à partir de jQuery 1.8, le résultat devrait être:

result = 3
result = 7
result = NaN

Parce que la première fonction then() renvoie une nouvelle promesse, et la valeur 7 (et c'est la seule paramètre qui sera transmis)est passé à la prochaine done() , donc le deuxième done() écrire result = 7 . Le deuxième then() prend 7 que la valeur de a et prend undefined comme valeur de b , la seconde then() renvoie une nouvelle promesse avec le paramètre NaN, et le dernier done() imprime NaN comme son résultat.

4
répondu JasmineOT 2015-07-06 13:35:44

il y a une cartographie mentale très simple en réponse qui était un peu difficile à trouver dans les autres réponses:

1
répondu B M 2017-12-08 16:24:37

.done() met fin à la chaîne promise, en s'assurant que rien d'autre ne peut attacher d'autres étapes. Cela signifie que l'implémentation de la promesse jQuery peut jeter n'importe quelle exception, puisque personne ne peut la gérer en utilisant .fail() .

en termes pratiques, si vous n'avez pas l'intention de joindre plus d'étapes à une promesse, vous devez utiliser .done() . Pour plus de détails, voir pourquoi les promesses doivent être faites

-5
répondu gleb bahmutov 2014-10-30 14:27:40