Say that I have the following code:
function testA {
setTimeout('testB()', 1000);
doLong();
}
function testB {
doSomething();
}
function doLong() {
//takes a few seconds to do something
}
I execute testA(). I have read that Javascript is single-threaded. What happens after 1000 milliseconds, when the timeout for testB() is reached?
Some possibilities I can think of:
testB() is queued up to execute after doLong() and anything else it called have finished.
doLong() is immediately terminated and testB() is started.
doLong() is given a little while longer to execute before being stopped (either automatically or after prompting the user) and testB() is started.
doLong() is paused, testB() is started. After testB() has finished, doLong() resumes.
What is the correct answer? Is it implementation dependant or part of the standard?*
This question is similar but not the same, as far as I can tell.
Any links that you can recommend for better understanding Javascript execution would be appreciated.
Thanks!
*Yes, I know that not all browsers follow standards :(
The first of your guesses is the correct one:
testB() is queued up to execute after doLong() and anything else it called have finished.
If it takes more than one second for testA to finish, testB will simply have to wait.
Also, you should write setTimeout(testB, 1000) rather than setTimeout('testB()', 1000). Sending a string to setTimeout is, like using eval, generally considered evil and will make you enemies ;)
Related
function printNumbers(from, to) {
let current = from;
function go() {
alert(current);
if (current < to) {
setTimeOut(go, 1000); //recursion to function go()
}
current++; // because of recursion execution should not reach this point
}, 1000);
}
printNumbers(5, 10);
Please explain to me why ^current++^ works immediately? but because of recursion it should not work. isnt it? please explain me who understand how it work and why
setTimeout is not blocking. It puts a function on a queue to be called when some time has passed. The rest of the function still executes without pause.
There is no return statement or anything else that would stop the JS engine from reaching the current++; statement.
To supplement Quentin's answer, this setTimeout(go, 1000) line (FYI, setTimeout is the proper spelling, not setTimeOut) isn't actually doing any recursion. It's passing off a function go to be called after 1000 ms in the event loop after the stack empties (the same stack that can do recursion and overflow). It's incidental that this all happens within the same function that's passed as a parameter to the timeout which makes it visually look recursive.
What happens is the setTimeout line runs and adds the function go to the event loop and guarantees a delay of at least 1000 ms. Then, the rest of the synchronous code runs, including the rest of go and current++;. Later on, when the stack is empty, tasks on the loop are executed in order, including go (assuming the 1000 ms timer has elapsed).
This explains why code like:
(function run() {
requestAnimationFrame(run);
// do stuff
})();
never overflows the stack: it's not actually recursion and each call frame is destroyed before the next call happens.
As an aside, it may be surprising that
(function run() {
requestAnimationFrame(run);
// do stuff
})();
and
(function run() {
// do stuff
requestAnimationFrame(run);
})();
behave pretty much the same. The reason is that the next run callback is guaranteed to execute once all synchronous code (the current call to run and anything else on the call stack) completes execution, so it's not like the location causes a block in synchronous execution and the child call gets to do work as would be the case with recursion.
I was trying to create a loop in Chrome console with Javascript that executes the same function all the time. Instead it doesn't output anything and it actually just increases Chromes memory size until it crashes. Any advice on what's going wrong here?
while(true){
window.setTimeout(function (){
console.log("Hello");
}, 4000)}
You're creating an immense number of setTimeout events, all of which are created immediately in rapid succession and scheduled to be invoked 4000 ms after their creation.
Seems like you're looking for .setInterval() to perform a continuous invocation.
window.setInterval(function() {
console.log("Hello");
}, 4000);
To do it with setTimeout, you'd still not use any kind of imperative loop. You'd have the callback set up another setTimeout when it runs.
window.setTimeout(function f() {
console.log("Hello");
setTimeout(f, 4000);
}, 4000);
I gave the callback function the name f so that it could be used for the next timer.
In general, you don't "pause" your script. You schedule things to be done at a later time, and allow code to continue running until then. That's why you had a problem. The scheduled timer didn't pause anything, so the loop just keep running at full speed.
I'm trying to write a Javascript function that calls doSomething() continuously, as long as some_condition is true. If some_condition becomes false, it should check after five seconds whether some_condition has again become true, and if not, display an error message on the screen.
I currently have this much of the function written, but am confused about whether I am doing this correctly. Thanks for the help.
while (some_condition) {
doSomething();
else {
???
}
No, you should not use a while loop. JavaScript is single threaded, and if you have a while loop that never returns, the browser (or your JavaScript environment of choice) will become unresponsive.
You need to use setTimeout to schedule the function.
function enqueueSomething() {
if (some_condition)
doSomething();
// Enqueue ourselves to run again without blocking the thread of execution
setTimeout(enqueueSomething);
else
// Wait 5 seconds, then try again
setTimeout(enqueueSomething, 5000);
}
You'll need to maintain some state that indicates whether you've previously waiting 5 seconds, and add your error-alerting code.
Does
setTimeout(function () { /*logic*/ }, 0);
Really makes the function to be asynchronous?
No, it does not make the function asynchronous - if the function takes some time it will still block the thread.
However, setTimeout puts this function onto the Browser's Event Queue. So it will be executed after all other events which are already on that queue and are waiting to get executed (and would be executed after your scriptblock is finished if you weren't using the timeout).
To be precise, setTimeout(xxx,0) does make no sense, the minimum delay is 4ms, as stated in the spec.
Altogether the timing is a bit more complex than I explained here, but this might be sufficient as toplevel explanation;) For more info, check John Resig's Article.
No it does not.
It just places the function on the event queue with the given delay (here a delay of zero). If there are any other functions currently queued up for execution, it gets placed behind them and has to wait until those (including the currently active) functions are executed.
To test this, you could do something like ethis
console.log( 'start' );
setTimeout(function () {
console.log("timeout");
}, 0);
// some very long running code
console.log( 'end' );
You will still get the output:
start
end
timeout
Not exactly
console.log("1");
setTimeout(function () {
console.log("2");
}, 0);
console.log("3");
You'll probably see the output...
1
3
2
The timeout will not block the execution of the code but ALL browsers enforce a minimum timeout delay.
Its a bit difficult to explain whole javascript timer thing. May be this will help you.
John Resig Blog: How does Javascript timers work
I am confused as to why the following html is not working.
I would expect it to keep sending alerts but it stops after one.
Furthermore, the "left fn" alert never occurs!
Can anyone explain this to me?
I am using html5 with javascript in firefox on ubuntu.
<!DOCTYPE html>
<script>
function alertme() {
alert ("in fn");
}
while (true) {
window.setTimeout(alertme(), 3000);
alert("left fn");
}
</script>
A few probable issues:
alertme() is being called immediately and its return value is instead being passed to setTimeout().
To fix this, you can pass alertme as a reference (without the calling parenthesis):
setTimeout(alertme, 3000);
However, this will then conflict with JavaScript's (primarily) single-threaded nature.
The setTimeout()s, being asynchronous, simply start a timer that expires no less than 3 seconds from now. But, they require that the one thread is eventually not busy for the delayed task to be performed.
However, the while (true) {}, being synchronous and indefinite, will keep the thread busy until all execution is stopped and will never allow the timeouts to perform their tasks. So, you will never see "in fn".
John Resig has a good write up on timers: http://ejohn.org/blog/how-javascript-timers-work/
How exactly to fix the code depends on the intent.
while (true) {
window.setTimeout(alertme, 3000); //setTimeout wants a function, not the return value of the function
alert("left fn");
}
btw, have fun with klicking all the messageboxes away...