Calling timeout inside an object, function get called immediately - javascript

I made a jsfiddle for you:
http://jsfiddle.net/fyJP2/
This is the code:
var chat = {
init: function(){
setTimeout( comet , 10);
}
};
function comet()
{
alert('called');
}
$(document).ready(function(){
chat.init();
});
As you can see comet() is called immediately ignoring completely the delay of 10 seconds, why? I am passing comet and not comet() as setTimeout requires, but the function is still executed.
I originally thought it was a scope issue so I moved comet to its own function, but doing this: http://jsfiddle.net/fyJP2/1/ the result is the same.
Can someone explain me why?

As has been pointed out the second argument passed to window.setTimeout is in milliseconds.
Therefore your code should be:
init: function(){
setTimeout( comet , 10000);
}
Presuming you meant ten seconds, that is.
Read more here: https://developer.mozilla.org/en/docs/Web/API/window.setTimeout

Related

setTimeout nuances in Node.js

I'm trying to understand how the callback function works inside the setTimeout function. I'm aware the format is: setTimeout(callback, delay) I wrote a little test script to explore this.
test1.js
console.log("Hello")
setTimeout(function () { console.log("Goodbye!") }, 5000)
console.log("Non-blocking")
This works as expected, printing Hello <CRLF> Non-blocking and then 5 seconds later, prints Goodbye!
I then wanted to bring the function outside of the setTimeout like this:
console.log("Hello")
setTimeout(goodbye(), 5000)
console.log("Non-blocking")
function goodbye () {
console.log("Goodbye")
}
but it doesn't work and there isn't a 5 second delay between Non-blocking and Goodbye!, they print straight after each other.
It works if I remove the brackets from the function call in the timeout, like this:
setTimeout(goodbye, 5000)
but this doesn't make sense to me because that's not how you call a function. Futhermore, how would you pass arguments to the function if it looked like this?!
var name = "Adam"
console.log("Hello")
setTimeout(goodbye(name), 5000)
console.log("Non-blocking")
function goodbye (name) {
console.log("Goodbye "+name)
}
My question is really, why doesn't it work when there are parameters in the function, despite the fact the setTimeout is being provided with a valid function with the correct syntax?
By putting the parentheses after your function name, you are effectively calling it, and not passing the function as a callback.
To provide parameters to the function you are calling:
You can pass an anon function. setTimeout(function(){goodbye(name)}, 5000);
Or, you can pass the arguments as a third parameter. setTimeout(goodbye, 5000, name);
Look at this question: How can I pass a parameter to a setTimeout() callback?
No matter where you place it, goodbye(name) executes the function immediately. So you should instead pass the function itself to setTimeout(): setTimeout(goodbye, 5000, name).
When you use it like this:
setTimeout(goodbye(), 5000);
it will first call goodbye to get its return value, then it will call setTimeout using the returned value.
You should call setTimeout with a reference to a callback function, i.e. only specifying the name of the function so that you get its reference instead of calling it:
setTimeout(goodbye, 5000);
To make a function reference when you want to send a parameter to the callback function, you can wrap it in a function expression:
setTimeout(function() { goodbye(name); }, 5000);
You can use parantheses in the call, but then the function should return a function reference to the actual callback function:
setTimeout(createCallback(), 5000);
function createCallback() {
return function() {
console.log("Goodbye");
};
}

Javascript Callback functions vs just calling functions

So i don't really understand the point of "callback".
Here is an example of callback:
function sayBye(){
alert("Bye!");
}
function saySeeYou(){
alert("See you!");
}
function sayHello(name,myfunc){
alert("Hello");
myfunc;
}
sayHello("Max",saySeeYou());
Whats the point of passing in a function when you can just call the function? like this code does the exact same:
function sayBye(){
alert("Bye!");
}
function saySeeYou(){
alert("See you!");
}
function sayHello(name){
alert("Hello");
saySeeYou();
}
sayHello("Max");
Whats the point of passing in a function when you can just call the function?
Usually, callbacks Javascript are used in Javascript for code that you want to run in the future. The simplest example is setTimeout: if you call the callback now then the code runs immedieately instead of after 500 ms.
//prints with a delay
console.log("Hello");
setTimeout(function(){
console.log("Bye");
}, 500);
//no delay this time
console.log("Hello");
console.log("Bye");
Of course, it would be really neat if we could write something along the lines of
//fake Javascript:
console.log("Hello");
wait(500);
console.log("Bye");
But sadly Javascript doesnt let you do that. Javascript is strictly single-threaded so the only way to code the wait function would be to pause the execution of any scripts in the page for 500 ms, which would "freeze" things in an unresponsive state. Because of this, operations that take a long time to complete, like timeouts or AJAX requests usually use callbacks to signal when they are done instead of blocking execution and then returning when done.
By the way, when passing callbacks you should only pass the function name. If you add the parenthesis you are instead calling the function and passing its return value instead:
//When you write
foo(10, mycallback());
//You are actually doing
var res = mycallback();
foo(10, res);
//which will run things in the wrong order
Your code is not correct as Felix Kling already pointed out. Besides this, passing a function instead of calling one directly allows you to insert different behavior, your code is more decoupled and flexible. Here an example:
function sayBye(){
alert("Bye!");
}
function saySeeYou(){
alert("See you!");
}
function sayHello(name,myfunc){
alert("Hello");
if (myfunc) {
myfunc();
}
}
sayHello("Max",saySeeYou);
// I'm inserting a different behavior. Now instead of displayng "See you!"
// will show "Bye!".
sayHello("Max",sayBye);
You are doing it wrong, you should do like bellow
Don't call the function just pass the function as callback
use this
sayHello("Max",saySeeYou); //here the second parameter is function
instead of
sayHello("Max",saySeeYou());//This will put the result of saySeeYou as second parameter
in say hello call the functiom
function sayHello(name,myfunc){
console.log("Hello");
myfunc();
}

Delay 6 seconds before beginning a function that will loop itself, small, not working, why?

I'm trying to create a 6 second delay before the heartColor(e) function begins, the function will then continue to loop. I don't understand why it's starting the function immediatley, and not waiting the 6 seconds it's supposed to, what did I do wrong?
function heartColor(e) {
e.animate({
color: '#7ea0dd'
}, 1000).animate({
color: '#986db9'
}, 1000).animate({
color: '#9fc54e'
}, 1000, function(){
heartColor(e)
})
}
$('.something').hover(function(){
setTimeout(heartColor($(this)), 6000);
})
The setTimeout() function expects its first parameter to be a function reference (or a string, but that's not recommended for several reasons). You are not passing it a function reference, you are calling the heartColor() function and passing the result to setTimeout(). So the function executes immediately, and then after six seconds nothing happens because the return value was undefined so setTimeout() had nothing to work with.
Try this instead:
$('.something').hover(function(){
var $this = $(this);
setTimeout(function() {
heartColor($this);
}, 6000);
})
The reason I have included an anonymous function as the parameter to setTimeout is that your call to heartColor() needs to pass a parameter through. If it didn't have any parameters you could do this:
setTimeout(heartColor, 6000);
Note there are no parentheses after heartColor - that gets a reference to the function without calling it so that later setTimeout calls it for you. But you can't get a reference to the function and provide parameters at the same time so you need to wrap the call up in another function. You could do this:
var $this = $(this);
function callHeartColor() {
heartColor($this);
}
setTimeout(callHeartColor, 6000);
My original answer with the anonymous function is kind of short hand for that and (most people find it) more convenient.
The reason I have created a variable $this is because of the way the this keyword works in JavaScript, which depends on how a function is called. If you simply said heartColor($(this)) inside the anonymous function (or the callHeartColor() function) this would not be the element being hovered over.
you are invoking the function heartColor instead of passing it as a parameter. you have to do:
$('.something').hover(function(){
setTimeout(function(){heartColor($(this))}, 6000);
})
You want this:
$('.something').hover(function(){
setTimeout(function() {heartColor($(this));}, 6000);
})

Repeat function execution start problem

I repeat execution of function on every second like
setInterval(function(){ /* some code */},1000};
What to change so function would be executed first time immediately and then repeats on every 1 second, any parameter I missed ?
You can use a self-executing function:
(function Fos () {
//do your stuff here
setTimeout(Fos, 1000);
})();
This function will invoke itself, and then set a timeout to run itself again in a second.
EDIT: Just one more note. In my example I used a named function expression (I used the name "Fos"), which allows us to reference the function itself inside the function. Some other examples use arguments.callee, which does not even work in ECMAScript 5 Strict mode, and generally not a recommended practice nowadays. You can read more about it in the SO question Why was the arguments.callee.caller property deprecated in JavaScript?
You might want to declare the function, run it and after that set the interval:
function something() { /* ... */ } // declare function
something(); // run it now immediately (once)
setInterval(something, 1000); // set an interval to run each second from now on
nope. the best you can do is:
var worker = function() { /* code */ }
worker();
setInterval(worker, 1000)
You could use a slightly different pattern like this:
(function() {
/*code*/
setTimeout(arguments.callee, 1000);
})()
Note that arguments.callee isn't allowed in strict mode, so then you could do something like:
var worker = function() {
/*code*/
setTimeout(worker, 1000);
}
worker();
The latter two code examples will create a function that will call itself 1000 milliseconds after executing. See this link for more details on the differences (advantages/disadvantages) between using setInterval() and setTimeout() chaining.
An additional solution to the ones already suggested is to return the anonymous function in its declaration, and calling the function immediately after it has been declared.
This way you don't have to use an additional variable and you can still use the interval ID returned by setInterval, which means that you can abort it using clearInterval later.
Eg. http://jsfiddle.net/mqchen/NRQBK/
setInterval((function() {
document.write("Hello "); // stuff your function should do
return arguments.callee;
})(), 1000);

setTimeout issue in Firefox

The menu system is supposed to expand and collapse according to a given delay using the following statements (o_item.getprop('hide_delay') returns 200 and o_item.getprop('expd_delay') returns 0):
this.o_showtimer = setTimeout('A_MENUS['+ this.n_id +'].expand(' + n_id + ');',
o_item.getprop('expd_delay'));
and
this.o_hidetimer = setTimeout('A_MENUS['+ this.n_id +'].collapse();',
o_item.getprop('hide_delay'));
I tried placing the code for the first argument into separate functions and call these functions as the first argument to setTimeout like this:
this.o_showtimer = setTimeout( expandItem(this.n_id, n_id),
o_item.getprop('expd_delay'));
Firebug produced the following error message:
useless setTimeout call (missing quotes around argument?)
And there was no delay in the collapse.
I placed the argument in quotes (though recommended against here) like this:
this.o_showtimer = setTimeout( "expandItem(this.n_id, n_id)",
o_item.getprop('expd_delay'));
but this didn't work. It appeared that nothing was happening at all and throwing some console.log() messages into the code confirmed this.
I tried using an anonymous function call as recommended here and here like this:
this.o_showtimer = setTimeout( function() { expandItem(this.n_id, n_id); },
o_item.getprop('expd_delay'));
but this didn't work either. It produced undesirable results in IE (items not collapsing is the same manner as before) and nothing happening in Firefox (placing console.log() statements in expandItem and collapseItem functions confirmed that they weren't being called).
I even tried doing the following:
this.o_hidetimer = setTimeout( function() { alert('test'); },
o_item.getprop('hide_delay'));
and that didn't even work! Seems there's something up with calling the anonymous function.
Discovered that assigning the value of setTimeout to a variable other than this.o_showtimer made the left argument of setTimeout fire. Must be something to do with assigning something to this.
If I do this:
var o_showtimer = setTimeout( function() { expandItem(this.n_id, n_id); },
o_item.getprop('expd_delay'));
expandItem gets called. However, if I do this:
var o_showtimer = setTimeout( function() { expandItem(this.n_id, n_id); },
o_item.getprop('expd_delay'));
this.o_showtimer = o_showtimer;
As if setTimeout can predict the future! (expd_delay is 0!).
I think the problem is in Javascript's idiosyncratic treatment of 'this'. When you call 'expandItem' within your anonymous function, you are not calling it as a method, so 'this' gets set to the fundamental scope (window).
I would suggest using a local variable
var that = this;
this.o_showtimer = setTimeout( function() { expandItem(that.n_id, n_id); },
o_item.getprop('expd_delay'));

Categories