Il y a en fait une différence assez critique, dans la mesure où les différés de jQuery sont censés être des implémentations de Promises (et jQuery3.0 essaie en fait de les mettre en spécification).
La principale différence entre done / then est que
.done()
TOUJOURS renvoie les mêmes valeurs promises / encapsulées avec lesquelles il a commencé, indépendamment de ce que vous faites ou de ce que vous retournez.
.then()
renvoie toujours une NOUVELLE 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ée l'a renvoyée.
Traduit de jQuery en promesses natives ES2015, .done()
c'est un peu comme implémenter une structure "tap" autour d'une fonction dans une chaîne Promise, en ce sens que, si la chaîne est à l'état "résoudre", transmettre une valeur à une fonction. 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));
Ceux-ci enregistreront tous les deux 5, pas 6.
Notez que j'ai utilisé done et doneWrap pour faire la journalisation, pas .then. C'est parce que les fonctions console.log ne renvoient en fait rien. Et que se passe-t-il si vous passez. Puis une fonction qui ne renvoie rien?
Promise.resolve(5)
.then(doneWrap( x => x + 1))
.then(console.log.bind(console))
.then(console.log.bind(console));
Cela enregistrera:
5
indéfini
Qu'est-il arrivé? Lorsque j'ai utilisé .then et que je lui ai transmis une fonction qui ne renvoyait rien, son résultat implicite était "non défini" ... ce qui bien sûr renvoyait une promesse [non définie] à la méthode then suivante, qui se connectait non définie. La valeur d'origine avec laquelle nous avons commencé a donc été essentiellement perdue.
.then()
est, au fond, une forme de composition de fonction: le résultat de chaque étape est utilisé comme argument pour la fonction à l'étape suivante. C'est pourquoi .done est mieux considéré comme un "tap" -> il ne fait pas réellement partie de la composition, juste quelque chose qui jette un œil à la valeur à une certaine étape et exécute une fonction à cette valeur, mais ne modifie pas réellement la composition en aucune façon.
C'est une différence assez fondamentale, et il y a probablement une bonne raison pour laquelle les Promesses natives n'ont pas elles-mêmes implémenté une méthode .done. Nous n'avons pas besoin de comprendre pourquoi il n'y a pas de méthode .fail, car c'est encore plus compliqué (à savoir, .fail / .catch ne sont PAS des miroirs des fonctions .done / .then -> dans .catch qui renvoient des valeurs nues ne le font pas "rester" rejeté comme ceux passés à. puis, ils résolvent!)