Can I use jquery done()
on "non-ajax" functions. I get the error Uncaught TypeError: Cannot call method 'done' of undefined
when I try to do something like this.
function countThreeSeconds() {
var counter = 0,
timer = setInterval(function () {
if (counter == 3) {
console.log("All done. That was three seconds.");
window.clearInterval(timer);
} else {
console.log("Not there yet. Counter at: " + counter);
}
counter++;
}, 1000);
}
(function(){
var timer = countThreeSeconds().done(function(){
alert("done");
});
}());
Thanks
JSBIN
Can I use jquery done()
on "non-ajax" functions. I get the error Uncaught TypeError: Cannot call method 'done' of undefined
when I try to do something like this.
function countThreeSeconds() {
var counter = 0,
timer = setInterval(function () {
if (counter == 3) {
console.log("All done. That was three seconds.");
window.clearInterval(timer);
} else {
console.log("Not there yet. Counter at: " + counter);
}
counter++;
}, 1000);
}
(function(){
var timer = countThreeSeconds().done(function(){
alert("done");
});
}());
Thanks
JSBIN
Share Improve this question asked Apr 18, 2013 at 21:28 12527481252748 15.4k34 gold badges116 silver badges241 bronze badges 1-
3
As you can see, you can't. jQuery has nothing to do with it. You can never call a method on
undefined
. jQuery methods don't just magically appear everywhere (thank goodness). You can call them on specific objects defined in the jQuery library and as described by jQuery's API. – user1106925 Commented Apr 18, 2013 at 21:30
3 Answers
Reset to default 15Make the non-ajax function return a promise object.
function countThreeSeconds() {
var counter = 0,
deferred = $.Deferred(),
timer = setInterval(function () {
if (counter == 3) {
console.log("All done. That was three seconds.");
window.clearInterval(timer);
deferred.resolve();
} else {
console.log("Not there yet. Counter at: " + counter);
deferred.notify(counter);
}
counter++;
}, 1000);
return deferred.promise();
}
(function(){
var timer = countThreeSeconds().done(function(){
alert("done");
}).progress(function(i){
console.log("in progress...",i);
});
}());
Since you're not returning anything from the function, it's perfectly valid JS behavior. To be able to use done
on the function, return jQuery.Deferred
object from it.
Something like this:
function countThreeSeconds() {
var defer = $.Deferred(function() { // do your stuff here });
return defer.promise();
}
Thomas, with something like this, you could make a Deferred object (and its promise) really work for you.
For example, you could make countThreeSeconds()
a raw, more generalized function, and have all progress/done reporting performed in the calling function.
function countSeconds(n) {
var dfrd = $.Deferred(),
counter = 0,
timer = setInterval(function() {
counter++;
if (counter < n) { dfrd.notify(counter); }
else { dfrd.resolve(); }
}, 1000);
return {
promise: dfrd.promise(),
timer: timer
};
}
(function() {
var timerObj = countSeconds(3);
timerObj.promise.progress(function(counter) {
console.log("Not there yet. Counter at: " + counter);
}).done(function() {
clearInterval(timerObj.timer);
console.log("All done. That was three seconds.");
alert("done");
});
}());
Thus, another function could call countSeconds()
with a different value, and handle progress and done situations differently.
For example :
(function() {
var timerObj = countSeconds(10);
timerObj.promise.progress(function(counter) {
$("#message").text("Counter = " + counter);
}).done(function() {
clearInterval(timerObj.timer);
$("#message").text('Complete');
});
}());