Reputation: 67
I know that we can use "return this" in object, e.g.:
var $ = {
name : function(){
alert("John");
return this;
},
age : function(){
alert(21);
return this
}
}
$.name().age()
When one function is completed next one will be called. But in JQuery there is such construction:
$.get(url).done(callback).fail(callback);
How it works? How: method "get" gets callback on time. Ajax request is async by default.
P.S. I am interested in realization without $.Defferred object.
Thanks.
Upvotes: 1
Views: 135
Reputation: 707786
Here's how $.get(url).done(callback);
works.
$.get()
returns an object. It returns that object immediately as soon as the async ajax call has been started (it does not wait until the ajax calls finishes). That object has a number of methods which includes the jQuery promise methods. One of those methods is .done()
. When you call .done(callback)
on that returned object it stores the callback in a list of callbacks in that returned object.
When the $.get()
function finishes sometime later, it then .resolves()
it's own promise which ends up looking for all the .done()
callbacks stored in the object and calls the callbacks one at a time.
So, in this sequence of events, .done()
is actually called immediately right after $.ajax()
finishes initiating the ajax call, but all .done()
does when it executes is store the callback for use later by $.ajax()
when the async operation finishes.
Whether you know it or not, when you use the $.get(url).done(callback)
construction, you are using a jQuery promise object and the promise API. It works pretty simply here because $.get()
creates the promise object for you (and returns it and will then .resolve()
or .fail()
it later) and all you have to do is specify .done()
, .fail()
or .then()
callbacks and most of the work is done for you. You don't have to manually create a deferred object or promise object - you can just use the one returned by the ajax call.
Here's a little async queue that supports chaining for visual effects with it's own .done()
handler: http://jsfiddle.net/jfriend00/tS8G3/
function domWrapper(elem) {
if (!(this instanceof domWrapper)) {
return new domWrapper(elem);
}
if (typeof elem === "string") {
elem = document.getElementById(elem);
}
this.elem = elem;
this.q = [];
this.timer = null;
this.doneCallbacks = [];
}
domWrapper.prototype = {
hide: function() {
this.q.push({op: "hide"});
this._exec();
return this;
},
show: function() {
this.q.push({op: "show"});
this._exec();
return this;
},
delay: function(t) {
this.q.push({op: "delay", time: t});
this._exec();
return this;
},
done: function(fn) {
this.doneCallbacks.push(fn);
return this;
},
_exec: function() {
var next;
while (!this.timer && this.q.length) {
next = this.q.shift();
switch(next.op) {
case "show":
this.elem.style.display = "block";
break;
case "hide":
this.elem.style.display = "none";
break;
case "delay":
var self = this;
this.timer = setTimeout(function() {
self.timer = null;
self._exec();
}, next.time);
break;
}
}
// if all done with all pending activities
if (!this.q.length && !this.timer) {
// call the done callbacks
for (var i = 0; i < this.doneCallbacks.length; i++) {
this.doneCallbacks[i].call(this.elem);
}
}
}
}
function makeBlue() {
this.style.backgroundColor = "blue";
}
function makeBigger() {
this.style.width = "200px";
}
domWrapper("test").done(makeBlue).done(makeBigger)
.delay(2000).hide().delay(2000).show().delay(1000);
Upvotes: 4