Before we talked about MochiKit deferred,jsdeferred, now talk about jquery Deferred. First, let's start with their differences:
When the callback function is saved, MochiKit Deferred (Dojo Deferred) is saved with a 2-dimensional array with only two decimal groups, one for the successful callback, and one for the failure callback function.
Jsdeferred Each instance must have Ng,ok these two callback functions.
JQuery deferred a _deferred is responsible for adding a successful callback, and one is responsible for adding the error callback.
Their API differences are as follows:
Next, let's look at the source code of jQuery1.51:
This version of JQuery's deferred object is implemented using a two-strand structure, each of which is implemented by the deferred object returned by the _deferred method.
var promisemethods = "Then-Done fail isresolved isrejected promise". Split (""),
slicedeferred = [].slice;
Jquery.extend ({
_deferred:function () { //jquery static method, which is called in Deferred, see the Deferred method first.
var callbacks = [], fired, firing,cancelled,
Deferred = { //Call Jquery._deferred () method, returned object
Done:function () { ///According to the following example: var cb = $. Deferred ();d The parameter passed in the one method is Faildeferred.cancel, which is actually deferred.cancel.
if (!cancelled) { //If not canceled, enter the IF statement, just start with undefined, take non, so is true, enter the IF statement.
var args = arguments, I, length, elem, type, _fired;
if (fired) { //start is undefined, do not enter the IF statement.
_fired = fired;
Fired = 0;
}
for (i=0,length = args.length;i<length; i++) { //The parameters of the incoming done method are traversed, this is Faildeferred.cancel
Elem = Args[i];
Type = Jquery.type (elem); //Determine the type of each parameter
if (type = = = "Array") { ///If it is an array, call the Deferred.done method again.
Deferred.done.apply (Deferred,elem);
}else if (type = = = "function") { //If the type of the parameter is a function, add the function to the callbacks array. Here the Faildeferred.cancel is the function, so execute here.
Callbacks.push (Elem); //At this time callbacks = [Faildeferred.cancel]
}
}
if (_fired) { //undefined, do not enter the IF statement.
Deferred.resolvewith (_fired[0], _fired[1]);
}
}
return this; //this is the object that called the Done method
},
Resolvewith:function (context, args) {
if (!cancelled &&!fired &&!firing) { //According to the example, if there is no cancellation, no trigger, and no trigger, then enter the IF statement to trigger.
args = args | | [];
firing = 1; //Change the state so that the deferred is in the triggered State
try{
while (Callbacks[0]) {//callbacks = [Faildeferred.cancel, fun1]
Callbacks.shift (). Apply (context, args); The //shift method removes the first item of the array and returns the first item. The Faildeferred.cancel method is executed here. Because the Apply method is called, it is actually executing the Faildeferred.cancel method in the execution context of the CB. However, because in the Cancel method, it is not for the this operation, but for the private variable callbacks operation, so when the Faildeferred.cancel method is executed, the callbacks in the Faildeferred object is also manipulated. So at this point, the private variable in the Faildeferred object callbacks = [Deferred (partial) cancel] becomes []. This means that the CB Delay object triggers the Resolve method (a successful trigger). At this time CB callbacks = [FUN1], and then continue to cycle, take out fun1, execute. Then the callbacks array of CB and Faildeferred becomes [].
}
}finally{
Fired = [context, args];
firing = 0;
}
}
return this;
},
Resolve:function () {
Deferred.resolvewith (this, arguments); //resolve method is actually the implementation of Resolvewith method, here deferred is actually CB. Because the Execute var cb = $. Deferred (), CB refers to the Deferred object, callbacks and other properties. So these variables and attributes will be stored in memory, so when you call Cb.resolve, the deferred method of execution is actually the Resolvewith method of CB. The callbacks property inside is the callbacks property of the CB object.
return this;
},
Isresolved:function () {
Return!! (Firing | | fired);
},
Cancel:function () {
Cancelled = 1;
callbacks = [];
return this;
}
};
return deferred;
},
Deferred:function (func) { //is also a static method of jquery, which is the Deferred of jquery. There are two jquery._deferred () methods returned by the Deferred object
var deferred = jquery._deferred (), //Executes the static method of JQuery and returns a deferred object. Because the local variable Deferred here has the same name as the object returned by Jquery._deferred () Deferred, we call the local variable Deferred called the Deferred (variable)
faildeferred = jquery._deferred (), //Returns a Deferred object as well. Not the same as the deferred object above, but with the same methods and properties.
Promise
The Jquery.extend (deferred,{ ///Extension deferred variable refers to the deferred object instead of the Faildeferred object that is referenced by the. The deferred object has a default of Done,resolvewith,resolve,isresolved,cancel five methods. After the deferred (variable) object expands, six methods such as Then,fail,rejectwith,reject,isrejected,promise are added.
Then:function (Donecallbacks, failcallbacks) {
Deferred.done (donecallbacks). Fail (failcallbacks);
return this;
},
Fail:failDeferred.done, //When the deferred (variable) object calls the Fail method to add the failed callback function, the Faildeferred object that represents the failed method is actually called done.
RejectWith:failDeferred.resolveWith,
Reject:failDeferred.resolve, //When the deferred (variable) object triggers a failed callback method, that is, when the callback function that is added by the Fail method is triggered, The Resolve method that represents the failed Faildeferred object is called, and this method executes the callback function that is added by the done method in the Faildeferred object. This enables the successful callback of the deferred object and the operation of the failed callback (internally through two chains, a chain representing a success callback, and a chain representing a failure callback). That is, the failure callback is given to faildeferred object processing, and the successful callback is given to the deferred (variable) object to handle itself, and the deferred (variable) object is $. The object returned by Deferred ().
IsRejected:failDeferred.isResolved,
Promise:function (obj) { //This is a singleton method that returns only the same object, regardless of how many times the Promise method is called.
if (obj = = null) {
if (Promise) {
return promise;
}
Promise = obj = {};
}
var i = promisemethods.length;
while (i--) {
Obj[promisemethods[i]] = deferred[promisemethods[i]]; The //promise object has then,done,fail,isresolved,isrejected,promise six methods, it does not have a method to trigger the callback, so the Promise object can only add a callback method and cannot trigger the execution of the callback method.
}
return obj;
}
});
Deferred.done (Faildeferred.cancel). Fail (deferred.cancel); //Call the Done method of the deferred (variable) and the Fail method. Let's take a look at these two methods, please go to see _deferred (). When the done method is executed, the private variable in the deferred (variable) object callbacks = [Faildeferred.cancel], returns the deferred (variable), and then calls its Fail method. Its Fail method is the Faildeferred.done method. The Faildeferred.done method is the done method of the deferred object, and the passed argument is the deferred (variable) Cancel method. After executing the Fail method of the deferred (variable), the private variable in the deferred (variable) object callbacks = [Faildeferred.cancel]. The private variable in the Faildeferred object callbacks = [Deferred (partial) cancel].
Delete Deferred.cancel; //Remove the Cancel method for deferred (local).
if (func) {
Func.call (deferred,deferred); //For an example: if the var cb = $. Deferred (), when a function func is passed in, the function is executed in the context of the execution of the Deferred (local) object, and the object is passed as a parameter to the function func.
}
return deferred; //Returns the deferred (local) object.
},
When:function (Firstparam) {
var args = arguments, I =0, length = args.length, count = length;
var deferred = length <=1 && firstparam && jquery.isfunction (firstparam.promise)? FirstParam:jQuery.Deferred (); //If only one deferred or promise object is passed in. , the object is directly used, otherwise a new deferred object is generated.
function Resolvefunc (i) { //define Private function
return function (value) {
Args[i] = arguments.length > 1? Slicedeferred.call (arguments, 0): value; //slicedeferred is the [].slice method. Args[0] is the cb1.resolve () parameter value passed in, Args[1] is the value of the parameter passed in Cb2.resolve ().
if (! ( --count) { //If all deferred in the incoming when trigger the Resolve method, count will become 0, and therefore true, Cb3 resolve method is triggered.
Deferred.resolvewith (Deferred,slicedeferred.call (args,0));
}
}
}
if (length > 1) { //if 2 and more than 2 deferred objects are passed in
for (; i < length; i++) {
if (Args[i] && jquery.isfunction (args[i].promise)) { //If the parameter passed in is the deferred object
Args[i].promise (). Then (Resolvefunc (i), deferred.reject); //Fetch to Deferred's Promise object, call it's then method. The then method is: function (Donecallbacks, failcallbacks) {Deferred.done (donecallbacks). Fail (failcallbacks); return this;}, The then method can add both a success callback and a failed callback. Here's an example: var CB1 = $. Deferred (); var CB2 = $. Deferred (); var cb3 = $.when (CB1, CB2). Done (function Fun3 () {CB1 and CB2 all triggered successfully}); CB1 the successful callback array callbacks=[resolvefunc[0]], the failed callback array CALLBACKS=[CB3.REJECT],CB2 the successful callback array callbacks=[resolvefunc[1]], The successful callback array for the failed callback array callbacks=[cb3.reject],cb3 is callbacks = [FUN3]. At this point, if you trigger the Resolve method of CB1 and CB2, then the Resolve method of CB3 is triggered. If you only trigger one of the resolve methods in CB1 or CB2, then the Resolve method of CB3 will not be triggered and will be triggered if CB1 and CB2 methods are triggered. If you trigger any of the reject methods in CB1 or CB2, then the Reject method of cb3 is triggered.
}else{
--count; //If the incoming is not a deferred object, count will be reduced to 0. If there is one, it will not be equal to 0.
}
}
if (!count) { ///If 0, this method is executed. As an example: $.when ("Chaojidan", "Chaojidan1", "chaojidan2")
Deferred.resolvewith (Deferred,args);
}
}else if (deferred!== firstparam) { //If a deferred object is not passed in or a parameter is passed in that is not a deferred object. For example: var cb = $.when () or $.when ("Chaojidan")
Deferred.resolvewith (deferred,length?[ Firstparam]: []);
}
return Deferred.promise (); //If a deferred object is passed in, it is returned directly to its promise object. As an example: var cb = $. Deferred (); var CB1 = $.when (CB), at this time the CB1 is actually the promise object of CB. In other cases, a new deferred promise object is returned.
}
})
This snippet of code, according to this example: var cb = $. Deferred (); Cb.done (function fun1 () {alert (1)}), Cb.resolve (), to explain. From the above, when calling the var cb = $. Deferred (); After the method, the private variable in the Callbacks=[faildeferred.cancel],faildeferred object of the CB callbacks = [Cb.cancel], when called Cb.done ( function fun1 () {alert (1)}) After the method, the CB Callbacks=[faildeferred.cancel, fun1],faildeferred unchanged, when the Cb.resolve () method is called; is actually called Deferred.resolvewith (CB, []); Please see this method explained. Eventually, the private variable callbacks of CB and Faildeferred will become [].
This is the first generation of jquery deferred module, in the jquery1.6,1.7,1.8, are optimized, the next lesson explained.
Come on!
33rd lesson: JQuery Deferred