I am getting into sort of confusion here. Please go through the below code,
<script>
setInterval(function1,3000);
setInterval(function2(),3000);
function function1() {
console.log("Function1 called....");
}
function function2() {
console.log("Function2 called....");
}
</script>
As you can see I have two setInterval functions one calls function like function1 and another function2(). The output of first is perfect that gets called every 3sec and first call after 3sec. But second one gets called without the delay i.e function2.
I guess that () might be doing things there but I'm not sure about what I'm missing there. I just want to know what is happening there.
setInterval(function1,3000); instructs the JS engine to execute the function function1 every 3 seconds.
setInterval(function2(),3000); instructs the JS engine to run function2 once, then run the return value every 3 seconds. This return value is empty.
For a bit of fun try
function function2() {
console.log("Function2 called....");
return "function3();"
}
function function3() {
console.log("Function3 called....");
}
setInterval(function2(),3000);
Edit
In reponse to #harsha's comment: What do I mean by "run the return value"
setInterval(function2(),3000); will trigger the following workflow:
Initiate executing function2() (execute it, because it the brackets are given).
function2 runs to completion, then returns.
In your OQ, there is no return value from the function so it is null
The return value of my function2 is the string "function3();"
This return value is now inserted into the setInterval() call
The OQ version results in setInterval(null, 3000);, which does nothing every 3 seconds
My version results in setInterval("function3();", 3000), which calls eval("function3();"); every 3 seconds, which in turn runs function3 every 3 seconds.
In the second setInterval you are executing it right away and plugging the value returned by that function into setInterval.
For example,
setInterval(a(), 5000);
function a(){
return function(){
console.log("Executed!");
};
};
a() executed and returning the function into setInterval. You should see the console is writing Executed every 5 seconds.
This is just like math:
f(x) = x + 1
g(x) = 2
f(g(2)) = g(x) + 2 = 4
You replace g(2) with whatever it returns
(you replace a() with the function in this case)
http://jsfiddle.net/DerekL/39wNn/
The () makes the function get executed immediately in the second case. In the first case, just the pointer to function which gets executed later as the call back function.
Related
How come I can say:
var myFunction = function() {
setTimeout(myFunction, 1000);
}
myFunction();
Why does the function call in the setTimeout not require parentheses, but the last line does?
Nutshell
myFunction references the function
myFunction() calls the function
More Words
setTimeout expects a function reference* as an argument.
There are circumstances where setTimeout(myFunction(), 1000) might make sense, like if myFunction() returns a function, e.g.
function myFunction() {
return function() {
alert("ohai")
}
}
// Or
const myFunction = () => () => alert("ohai")
So:
setTimeout(myFunction(), 1000);
setTimeout gets the return value of myFunction
myFunction returns a function (that calls alert)
meaning there will be an alert every second.
See also Why function statement requires a name?
* Or a string to be evaluated, but a reference is preferred.
myFunction is a function
myFunction() calls the function and yields whatever value the function returns.
The purpose of setTimeout is running code after some time elapses. You need to pass just the function to it (so setTimeout can itself call the function when appropriate) because if you called the function (with the parenthesis) before passing it to setTimeout it would execute now instead of after 1 second.
When you use the parenthesis, it's saying 'call this function now'. So if you say setTimeout(myFunction(),1000);, it will use the return value of the function as the callback for the timeout. If the return value for the function is not itself a function, you'll get an error because it will try to execute something that isn't executable after the timeout (a string, a number, undefined, etc).
In line 2, the function myFunction is not called, but passed as an argument to the setTimeout function, whereas in line 4 myFunction is called; to call a function, you always have to use parentheses, even if there are no arguments.
I think this example would make it clearer if i may,
function callback() {
console.log('this function runs on page loads.');
}
setTimeout(callback(), 2000);
Here callback() function will run immediately after page loads and won't wait 2 seconds.
function callback() {
console.log('this function runs after page loads.');
}
setTimeout(callback, 2000);
Here callback() function will run after 2 seconds.
I am a bit confused about setTimeout.I want to confirm whether the output for the following code will always be:
inside abc
inside sample
The code:
function abc() {
xyz();
// interactions and modifications in DOM
$("#id1").append("something");
$("#id2").val("set something");
$("#id3").after("create some dynamic element");
// 10 to 20 interaction more...
console.log('inside abc');
}
function xyz() {
setTimeout(function() {
sample();
},0);
}
function sample() {
console.log('inside sample')
}
It would be great,if somebody could explain the whole flow with the call stack.
Yes, it will always have that output.
The callback inside a setTimeout will not be called until the execution context is clear - i.e. the currently executing sequence of code has finished.
This means that even if you do
setTimeout(function () { console.log("1 second!"); }, 1000);
var start = +new Date();
while ((+new Date()) - start < 5000) {}
1 second! will not be logged any sooner than 5 seconds have passed.
setTimeout() will run asynchronously after finishing current execution block. So output should be same always:
inside abc
inside sample
Javascript internally manage an event queues internally for all async tasks. Every time it checks its async queue after finishing current execution block.
Yes, the console output will always be the same. setTimeout's callback function is executed asynchronously after the context that called it is cleared. When setTimeout is called, it places its callback function on the stack and returns to the current execution context. When that is done (in your example, when abc is fully executed), the callback function is executed, which in your example basically calls sample immediately. So your code output will never be different.
The fact that setTimeout's callbacks are themselves executed asynchronously can be seen if you placed a longer setTimeout function somewhere inside abc before calling xyz:
function abc() {
setTimeout(function(){
console.log('wait')
},1000);
xyz();
console.log('inside abc');
}
function xyz() {
setTimeout(function(){
sample();
} ,0);
}
function sample() {
console.log('inside sample');
}
abc();
...your console will log:
inside abc
inside sample
wait
To hold sample's execution until the longer timeout is complete you would need to place the setTimeout calling sample inside the longer setTimeout.
If setTimeout's callback is ever behaving differently, it's most likely due to being accidentally passed a function call instead of a function pointer, like this:
setTimeout(sample(),0);
instead of
setTimeout(sample,0)
Also, just in case you didn't know (or for others), you can add
debugger;
at any point(s) in your Javascript code and then run the code to view the callstack at that point using dev tools (in Chrome it is in the right panel under 'Sources').
I have the code:
if (xxx == xxx){
var x = 5 + 3;
setTimeout(function() {
$('.regErrMsg').text("");
$scope.errMsg = "Hi.";
}, 5000);
}
I would like to execute the function i.e, show "Hi" message after 5 seconds. So, is my code correct. As of now, the message is not showing up. Where have I gone wrong?
My question is .. does the Hi executes and then it waits for 5 sec or wait waits for 5 secs and then shows Hi ?
Let's consider a simplified example
foo();
setTimeout(function () {bar();}, 5000);
baz();
Now it's easier to describe what will happen, step by step (in excruciating detail)
Line 1: foo gets interpreted
() invokes foo
Line 2: setTimeout gets interpreted
The arguments to be passed into setTimeout are interpreted, i.e. function references set here
The (/* ... */) invokes setTimeout
setTimeout sets up a callback to invoke argument 0 after argument 1 milliseconds
Line 3: baz gets interpreted
() invokes baz
End of file ...nothing happens for a while...
argument 0 (from 5) gets invoked
bar gets interpreted (using references from 4)
() invokes bar
As of now, the message is not showing up. Where have I gone wrong?
It looks like the only change you've made that will be reflected in the DOM is the clearing of text from .regErrMsg, perhaps you meant to use
$('.regErrMsg').text("Hi.");
or invoke some other method which will make the updated vale of $scope be reflected in the #document
The "problem" with setTimeout inside your controller is that angular is not going to watch the content of the scope after the function in the setTimeout is called.
Solution 1
You can do $scope.$apply() to force the view to update, eg:
setTimeout(function() {
$scope.errMsg = "Hi.";
$scope.$apply();
}, 5000);
Solution 2
They is a special function $timeout which will trigger the view refresh automatically after the function has been called. It has the same signature as setTimeout.
$timeout(function() {
$scope.errMsg = "Hi.";
//You don't need $scope.$apply() here
}, 5000);
You should inject $timeout into your controller
I have removed the $('.regErrMsg').text(""); because you shouldn't change the dom inside a controller.
If i'm calling 2 or 3 times a function, like this:
somefunction();
somefunction();
How could i know when is the last time the function has been called?
i'm asking that because i want the last function to do one more thing.
Pass a parameter that determines whether the function should do "one more thing"
somefunction(false);
somefunction(true);
You could set a timeout when the function is called, then the code will be called as soon as you exit from your first function returning control to the browser:
var timer = null;
function somefunction() {
// do something
if (timer == null) {
timer = window.setTimeout(function(){
// do one last thing
}, 0);
}
}
Demo: http://jsfiddle.net/Guffa/Fa5j3/
You can't know this.
If you know how often it is called, you can count down a variable.
If you don't know how often it is called you can start a timeout and call the special function. If you call someFunction again you cancel the old timeout and start a new timeout.
In the application I'm building I'm polling for a status update and I have noticed that if the call is made as follows the timeout fires continuously:
setTimeout($.get("http://localhost:8080/status", function(data) { UpdateStatus(data);}), 1000);
While if use a function instead the timeout fires every 1000 ms:
setTimeout(function() {$.get("http://localhost:8080/status", function(data) { UpdateStatus(data);})}, 1000);
Why?
In the first example, you're calling $.get and then passing its return value into setTimeout. In the second example, you're not calling the function at all; you're giving setTimeout a function that it will call later, which will then call $.get for you.
This is easier to see with a simpler test case:
function test() {
alert("Hi there!");
}
// WRONG, *calls* `test` immediately, passes its return value to `setTimeout`:
setTimeout(test(), 1000);
// Right, passes a reference to `test` to `setTimeout`
setTimeout(test, 1000);
Note that the first one has parentheses (()), the second one doesn't.
When you want to pass parameters to the function, you have to do it indirectly by defining another function:
function test(msg) {
alert(msg);
}
// WRONG, *calls* `test` immediately, passes its return value to `setTimeout`:
setTimeout(test("Hi there!"), 1000);
// Right, passes a reference to a function (that will call `test` when called) to `setTimeout`
setTimeout(function() { test("Hi there!"); }, 1000);
In the first example the first parameter to setTimeout is getting assigned the result of $.get (wrong), whereas in the second example it is actually receiving a parameter of type function, which will be correctly evaluated as a set of javascript statements every x milliseconds.
You shouldn't be passing the result of a function call to setTimeout - there's no sense in doing that.
First argument should be the function itself, not the call.
Why it fires continuously - a strange side-effect, who knows :)