This question already has an answer here:
-
Why is my function call that should be scheduled by setTimeout executed immediately? [duplicate]
3 answers
I want to let an element fade in, and stay on the page for 7 seconds before it fades out. And I can cancel it anytime.
I defined the following functions. But when I called info_timeout.setup(ele, 'some msg here')
, the ele just faded in and faded out immediately.
Am I missing something?
var info_timeout = {
show_info: function(){
this.ele.html(this.msg).fadeIn('normal');
this.id = setTimeout(this.hide_info(), 7000);
},
hide_info: function(){
console.log(this.ele, this.id);
this.ele.fadeOut('slow');
delete this.id;
},
setup: function(ele, msg) {
this.ele = ele;
this.msg = msg;
this.cancel();
this.show_info();
},
cancel: function() {
if(typeof this.timeoutID == "number") {
clearTimeout(this.id);
delete this.id;
}
}
};
Thanks.
Several problems.
This invokes hide_info
right away. Parenthesis invoke a function-object! (or are used for applying precedence to expressions).
That is,
this.id = setTimeout(this.hide_info(), 7000);
Is [mostly] equivalent to:
var temp = this.hide_info() // call function ... uh, what?
this.id = setTimeout(temp, 7000) // temp is "return" value ("undefined" here)
Oops! That's not right :) So take away the parenthesis. This will pass the function-object itself to the setTimeout
. (Yes, functions are just objects in JavaScript. The expression this.hide_info
is first evaluated to a function-object and, if there is a (...)
after, it will invoke said function-object.)
this.id = setTimeout(this.hide_info, 7000)
However, it is still not correct because this
inside the timeout function (hide_info
) will be wrong! But this can be fixed with using a closure. (There are many great SO answers on the topic, feel free to search!)
var self = this
this.id = setTimeout(function () {
// now in hide_info "this" will be "self", which was "this" ... outside :)
self.hide_info()
}, 7000)
(Or use Function.bind
from ECMAScript ed5 or a library.)
Additionally, this.id
is not the same as this.timeoutID
, and is suspect for "correctness".
Keep it simple. It's okay to pass undefined/0 to clearTimeout: it'll silently ignore you.
cancel : function () {
clearTimeout(this.id) // but id is a horrid overloaded name :)
this.id = undefined
}
Happy coding.