deferred.promise() et .promise()
La syntaxe de ces deux API est quasiment la même, mais il existe de grandes différences. deferred.promise() est une méthode d'instance Deferred, qui renvoie une instance Deferred.Promise. Un objet Deferred.Promise peut être compris comme une vue de l'objet différé. Il contient uniquement un ensemble de méthodes de l'objet différé, notamment : done(), then(), fail(), isResolved(), isRejected(), Always() ,Ces méthodes ne peuvent observer que l'état d'un objet différé, mais ne peuvent pas modifier l'état interne de l'objet différé. Ceci est très approprié pour l’encapsulation API. Par exemple, le détenteur d'un objet différé peut contrôler l'état de l'état différé (résolu ou rejeté) selon ses propres besoins, mais il peut rendre l'objet Promise de cet objet différé à d'autres observateurs, et les observateurs ne peuvent observer que le changements d'état.La fonction de rappel correspondante, mais ne peut pas changer l'état interne de l'objet différé, offrant ainsi une bonne protection d'isolement.
deferred.promise()
$(function(){ // var deferred = $.Deferred(); var promise = deferred.promise(); var doSomething = function(promise) { promise.done(function(){ alert('deferred resolved.'); }); }; deferred.resolve(); doSomething(promise); })
// Existing object var obj = { hello: function( name ) { alert( "Hello " + name ); } }, // Create a Deferred defer = $.Deferred(); // Set object as a promise defer.promise( obj ); // Resolve the deferred defer.resolve( "John" ); // Use the object as a Promise obj.done(function( name ) { this.hello( name ); // will alert "Hello John" }).hello( "Karl" ); // will alert "Hello Karl"
deferred.promise() empêche simplement un autre code de changer l'état de cet objet différé. On peut comprendre que l'objet de promesse différée renvoyé par la méthode deferred.promise() n'a pas de méthodes de résolution, de rejet, de progression, de résolution, de rejetAvec, de progressionAvec qui peuvent changer l'état. Vous ne pouvez utiliser que done, then, fail et autres. méthodes pour ajouter des gestionnaires ou juger le statut.
deferred.promise() ne peut pas changer l'état de l'objet différé, et ne garantit pas non plus que l'état actuel reste inchangé. Il garantit uniquement que vous ne pouvez pas modifier l'état de l'objet différé via l'objet de promesse différée renvoyé par différé. promesse(). Si nous renvoyons directement dtd ici, cela fonctionnera toujours. La fonction de traitement .done attendra toujours dtd.resolve() avant de l'exécuter.
Pour l'exemple spécifique de ce blog, si nous modifions le code sous la forme suivante :
var dtd = $.Deferred(); // 新建一个deferred对象 var wait = function(dtd){ var tasks = function(){ alert("执行完毕!"); dtd.resolve(); // 改变deferred对象的执行状态 }; setTimeout(tasks,5000); return dtd; }; $.when(wait(dtd)) .done(function(){ alert("哈哈,成功了!"); }) .fail(function(){ alert("出错啦!"); });
Le résultat de cette exécution est le même que le résultat du retour de dtd.promise précédemment.
Quelle est la différence ? Si on change le code de $.when par ceci :
var d = wait(dtd); $.when(d) .done(function(){ alert("哈哈,成功了!"); }) .fail(function(){ alert("出错啦!"); }); d.resolve();
Nous constaterons que l'alerte ("Haha, réussi!") sera exécutée immédiatement, mais "exécution terminée" mettra 5 secondes à apparaître.
Mais si notre fonction d'attente renvoie finalement dtd.promise() ici, d.resolve() signalera une erreur car l'objet d n'a pas de méthode solve().
De même si nous changeons le code en :
var dtd = $.Deferred(); // 新建一个deferred对象 var wait = function(dtd){ var tasks = function(){ alert("执行完毕!"); dtd.resolve(); // 改变deferred对象的执行状态 }; setTimeout(tasks,5000); return dtd.promise(); }; dtd.resolve(); $.when( wait(dtd)) .done(function(){ alert("哈哈,成功了!"); }) .fail(function(){ alert("出错啦!"); });
On peut aussi constater que alert("Haha, réussi!") sera exécuté immédiatement, car l'objet différé dtd a été résolu() avant d'être passé en attente, et une fois l'objet différé résolu ou rejeté, le statut ne changera pas.
Ensuite, nous changeons le code $.wait en :
$.when( wait(dtd)) .done(function(){ alert("哈哈,成功了!"); }) .fail(function(){ alert("出错啦!"); }); dtd.resolve();
Nous constaterons également que alert("Haha, success!"); est exécuté immédiatement. Bien que lorsque wait(dtd) est exécuté, dtd n'a pas été résolu et la méthode wait renvoie dtd.promise(), mais The L'objet différé d'origine dtd est exposé à l'extérieur, et nous pouvons toujours changer son état de l'extérieur.
Donc, si nous ne voulons vraiment pas qu'un autre code change l'état de l'objet différé à l'intérieur de la méthode d'attente, alors nous devrions l'écrire comme ceci :
var wait = function(){ var dtd = $.Deferred(); // 新建一个deferred对象 var tasks = function(){ alert("执行完毕!"); dtd.resolve(); // 改变deferred对象的执行状态 }; setTimeout(tasks,5000); return dtd.promise(); }; $.when( wait()) .done(function(){ alert("哈哈,成功了!"); }) .fail(function(){ alert("出错啦!"); });
C'est-à-dire, n'exposez pas directement deferred, et enfin renvoyez deferred.promise(), afin que les autres codes ne puissent ajouter qu'un gestionnaire.
.promise()
Tout d’abord, ce n’est pas une méthode d’instances différées ! Cette méthode est une méthode d'instance jQuery. Cette méthode est utilisée pour renvoyer un objet Promise une fois qu'un ensemble de types d'actions (tels qu'une animation) est terminé, afin que l'écouteur d'événement surveille son état et exécute la fonction de traitement correspondante.
Cette méthode accepte deux paramètres facultatifs : .promise( [type,] [target] )
type : le type de file d'attente, la valeur par défaut est fx, fx est l'animation de l'objet jQuery
.
targetObject : l'objet auquel attribuer le comportement Promise,
Ces deux paramètres sont facultatifs. Le premier paramètre (me) n'a actuellement aucun autre type de valeur trouvé à l'exception de fx. Par conséquent, il est généralement utilisé pour surveiller les animations et effectuer certaines opérations une fois l'animation terminée.
Exemple : renvoyer directement un objet de promesse d'état résolu sans effet d'animation
var div = $( "<div />" ); div.promise().done(function( arg1 ) { // 将会被马上触发 alert( this === div && arg1 === div ); });
Exemple : Déclenchez la fonction d'écoute done() une fois tous les effets d'animation terminés
<!DOCTYPE html> <html> <head> <style> div { height: 50px; width: 50px; float: left; margin-right: 10px; display: none; background-color: #090; } </style> <script src="http://code.jquery.com/jquery-latest.js"></script> </head> <body> <button>Go</button> <p>Ready...</p> <div></div> <div></div> <div></div> <div></div> <script> $("button").bind( "click", function() { $("p").append( "Started..."); //每个div执行动画效果 $("div").each(function( i ) { $( this ).fadeIn().fadeOut( 1000 * (i+1) ); }); //$("div")包含一组div,在所有的div都完成自己的动画效果后触发done()函数 $( "div" ).promise().done(function() { $( "p" ).append( " Finished! " ); }); }); </script> </body> </html>