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
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()
.
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
})
.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?
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);
}
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!)
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.
il y a une cartographie mentale très simple en réponse qui était un peu difficile à trouver dans les autres réponses:
-
done
met en œuvretap
comme dans bluebird Promises -
then
met en œuvrethen
, comme dans ES6 Promesses
.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