Javascript stack and recursive calls - javascript

Assume the following method(Just curious, I'm hopefully fail in js)
foo(0);
function foo(i){
if(i<1000){
setTimeout(function(){foo(i+1);}, 1000);
}
alert('I am foo');
}
So if I got it true, it should alerts around 1000 I am foos after 1000 seconds.
So doesn't it bother the browser about keeping the is in a sort of big stack? it should be too much I think or I'm wrong?

Yes, you will alert 1000 "foo" messages with this code.
However, the browser will not get bothered by the amount of i variables. i is a local variable to foo and as a result, it is only kept around as long as foo is executing. Each time the setTimeout callback is finished executing, i and the entire function's footprint is eligible for garbage collection by the browser (which will happen at an opportune time).
The reason for this is that there is no preserved memory call stack here because of the use of setTimeout. setTimeout does not do anything with a returned value from foo and as a result there are no pointers in memory keeping that function nor its variable environment from being collected.

Your call stack will look like this as your code goes through it's loop:
main() [local foo]
main() -> foo [local i = 0]
main()
(empty)
setTimeout()
setTimeout() -> foo [local i = 1]
setTimeout()
(empty)
setTimeout()
setTimeout() -> foo [local i = 2]
setTimeout()
(empty)
over and over until i equals 1000.
It happens this way because setTimeout is a browser api that waits n amount of time and then inserts the callback into the callback queue. The callback will then get picked up by the event loop and executed when the callstack is empty.
So, no, you aren't in any danger of overloading the browser with stacks or vars or whatever you were worried about. Your callstack will remain small because each time foo is executed, it fires off a setTimeout and returns. the i will stay in memory until the setTimeout's callback gets executed, at which point a new i will be created within the scope created by executing foo. That new i will stay in memory until the next setTimeout executes, on and on.
Here's a video that may help explain how this works. http://www.youtube.com/watch?v=8aGhZQkoFbQ

Firstly in javascript there is no "int" you have to say var i. And it gets alone the type for the declaration. If you want get Information about stack. You can use the debug console. And navigate to the call stacks. Its a nice feature you have also a nice overview. I prefer the Chromes Debugger. You can get there with pressing F12

1000 is in a stack is not a really big size for a browser to deal with.
Moreover, there won't be more than 2 is at the same time (maybe even only one), with each function executing every second.
This code won't load 1000 calls to get triggered with an interval of 1 second, this will chain calls, preventing the stack to get bloated.

Related

How does the browser determine the order in which functions get invoked?

Given the following example:
for(var i=1;i<=5;i++){
setTimeout(function timer(){
console.log(i)
}, 0);
console.log(i);
}
This prints out:
1
2
3
4
5
6
6
6
6
6
setTimeout does not get executed immediately but rather after the loop has ended, despite the fact that console.log got executed immediately with each iteration within the loop.
I did a little research into this, but the most information I could find stated that although the anonymous function within setTimeout was added to the task queue that JavaScript executes, it doesn't necessarily get called immediately.
My question is that how does the browser determine which functions get priority in terms of execution?
The reason you are getting this response is that every time you enter the loop you are setting a new timeout.
Timeouts are put in the stack and executed when the loop is finished. This may confound you because when you use a function inside a function in synchronous code, the parent pauses its execution until the child finishes. But when an asynchronous function is called (just like setTimeout()) the behaviour is quite different.
Check this post: Asynchronous vs synchronous execution, what does it really mean?

Javascript timers in which order

See the below code
vat t = setTimeout(x, 1000);
vat t1 = setTimeout(y, 1100);
var t2 = setTimoue(z, 4000);
The order of execution is t, t1 and t2. So, t is executed after 1s. Till here is fine. Then is t1 executed after 100ms(1100 - 1000) or is it executed 1100ms after t is executed?
t1 will be executed 100ms after t was executed.
But actually, if the page is busy, setTimeout may be fired later so that it can less or greater than 100ms.
Above is the correct answer, although I would encourage you, going forward, when possible, to go open up the JavaScript console in your browser and figure it out yourself. console.log(Date.now()) in your code and test it. When I first got into coding, I would always turn to pros for simple questions (out of habit), but in my experience, being successful in coding often means knowing HOW to get the answer, as opposed to just knowing WHAT the answer is.
Additionally, I would argue you're much more likely to remember the answer if you identified it yourself instead of someone just telling you.
Good luck!
If you want to control the order of execution I really think you should sequence the timeouts.
var t = setTimeout(x, 1000);
function x(){
setTimeout(y, 100);
}
function y(){
setTimeout(z, 2900);
}
In any case I'm not sure you should be doing any of this in the first place.
If you want to call one function after another just use the .call or .apply.
take a look at: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
JavaScript is single-threaded. If some block of code uses execution thread, no other code can be executed. This means your setTimeout() call must wait until main execution finishes.
[from here]setTimeout behaviour with blocking code

Please explain example in nextTick documentation

Update: This turned out to be a really stupid question. I just failed to notice some simple things in the quoted example.
I've been looking at information about ticks and the event loop, and mostly it's clear, but there is an example in the nextTick documentation that puzzles me. It says:
It is very important for APIs to be either 100% synchronous or 100%
asynchronous. Consider this example:
// WARNING! DO NOT USE! BAD UNSAFE HAZARD!
function maybeSync(arg, cb) {
if (arg) {
cb();
return;
}
fs.stat('file', cb);
}
This API is hazardous. If you do this:
maybeSync(true, function() {
foo();
});
bar();
then it's not clear whether foo() or bar() will be called first.
First questions: why is foo not guaranteed to be called first? There is a simple function call (of maybeSync), an if, and a callback of cb=foo. I take it that something in this chain is in some way (possibly) asynchronous, pushing something to the event queue and continuing execution? I don't see how anything there could have that effect.
Second question: is there some documentation somewhere that could have helped me understand this on my own?
This is pretty straightforward. foo is guaranteed to be called first if there's no arg as well as foo is guaranteed to be called "last" if there is an arg. Just imagine call stacks here:
arg exists
maybeSync calls cb immediately within same event loop iteration. foo is called synchronously as well within same event-loop iteration
maybeSync returns - so fs.stat is never called in this case
bar is called after foo is done
arg does not exist
maybeSync calls fs.stat (which is asynchronous) providing cb as a callback
there's no more synchronous code to run within current event-loop iteration thus bar is called
fs.stat is complete and it calls cb on the next event loop iteration (after bar). foo executes synchronously, but within another event loop iteration this time
Both are quite obvious. The problem here is that in most cases you don't know in advance if there's any arg value (otherwise there's no need in if :)) so you could have two scenarios of running this code which makes things pretty complicated.
process.nextTick mimics async nature of fs.stat here, so that foo is always called on the next event loop iteration making the flow predictable.

Do nothing if the same function is already running

I have a javascript function that runs every 3 seconds, is there any way to do nothing if a previous instance of the function is already running?
I assume you are running heavy function with setInterval and want to skip one tick if previous one has not completed.
Then, instead of
function yourfoo() {
// code
}
setInterval(yourfoo, 3000);
do:
function yourfoo() {
// code
setTimeout(yourfoo, 3000);
}
setTimeout(yourfoo, 3000);
This guarantees next call is not scheduled until previous one is completed.
you could define a boolean flag to indicate the running state of the function on a higher scope, and switch it on or off accordingly.
Yes.
This is done by default.
It's called JavaScript is single threaded.
Two functions can't run at the same time.
Your probably using setInterval which will internally buffer function calls until any currently running code is finished.
JavaScript is single threaded, meaning that only one block of JavaScript will get executed at a given time. So even when the timer fires the execution of the code will be queued until the next available moment. Important to know is that if you're using a setInterval only one interval "fire" will get queued and all others will be dropped until there are no more intervals of this type on the queue.
Here's a great explanation of how this works by jQuery's father John Resig: http://ejohn.org/blog/how-javascript-timers-work/
You could rewrite your code to use setTimeout, because that way you're guaranteed that the next executing of the code will only take place after waiting at least the stated number of milliseconds (can be more if execution is blocked). Using setInterval the blocking could result in a back-to-back execution of the code if the code takes a long time to finish.
So, do something like this to prevent the back-to-back execution:
var nrOfMillisecondsToWait = 200;
setTimeout(function() {
.. your code here
}, nrOfMillisecondsToWait);

Which is better to execute window.setTimeout

Which option is better to execute window.setTimeout and why?
Option A:
window.setTimeout(somefunc,0);
Option B:
window.setTimeout(somefunc,n); //n may be any number >0
Thanks.
The thing about a timeout or an interval, they always wait for the current thread to run out before they execute their own function- even if you put it in the first line.
var color='white';
setTimeout(function(){alert(color+' from timeout')}, 0);
for(var i=0;i<100001;++i){
if(i=100000)alert(color='green');
}
alert(color='red')
Option A will simply call somefunc with the additional overhead of needlessly calling setTimeout (since your second parameter means 0 milliseconds of delay). Option B is for if you intend to have a delay prior to the execution of somefunc. Could you elaborate a bit please, or does this answer your question?
It depends on what you want to do.
setTimeout(somefunc,0) is not so different with just calling somefunc
(but I guess .setTimeout(somefunc,0) will finish current block first and then called somefunc)
If you need to wait browser rendering, and run somefunc after that, use window.onload or jQuery's $(document).ready
window.setTimeout(somefunc,0);
will run somefunc right away (but won't wait for a return value before continuing)
window.setTimeout(somefunc,n);
will wait n milliseconds before running somefunc (but won't wait for it to start or return before continuing)
or if you call somefunc() without the timeout it will run somefunc but wait for it to finish before continuing.
consider setTimeout to be like "starting" a new thread.
I recall having some browser issues when using setTimeout (func, 0) so now I do setTimeout (func, 1) whenever I want to have the shortest delay. Note that for most (all?) browsers the real shortest delay is some number n > 1 (definately n > 0 and probably n < 50).
Which browser I was having issues with I don't remember.
Note setTimeout(fn,0) doesn't necessarily ensure that the function fn will be called right after the current callstack unrolls - might not be a very important distinction.
It IS possible for the browser to have put something on the event before your code hit
setTimeout(fn, 0) [maybe the code preceding the setTimeout involved some CPU intensive calculations]. See example here
function clickHandler () {
spinWait(1000);
setTimeout(relayFunc, 0);
//the jsFiddle link shows that relayFunc
//will not be called after the clickHandler
//if another event was queued during spinWait()
}
For a usage of setTimeout other than the common 'let dom elements render first', see my blog here

Categories

Resources