html5 and javascript: is setTimeout breaking this? - javascript

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...

Related

Why does setTimeout not trigger after specified time

I am running a very basic javascript code in Viusal Studio Code. However I am not seeing the callback function get triggered.
I am trying to understand how setTimeout() works in javascript. I am running the following code (in file called test.js) in Visual Studio code as follows:
node test.js
'use strict'
let timerexpired = false;
setTimeout( function() {console.log(`setting timerexpired to true...`);
timerexpired = true;
},
5000);
while(1) {
console.log(`timerexpired = `, timerexpired);
if (timerexpired) {
console.log(`timer expired. Resume execution`);
break;
} else {
console.log(`keep on spinning`);
}
}
Expect the loop to break after 5000 ms. But it keeps on spinning with output as "keep on spinning"
When you call setTimeout or when you do any blocking operation for that matter, it's in fact added to an event table and not executed immediately.
It's only after the call stack is empty that the event loop check the event table to see if there's anything waiting, and move it to the call stack.
To better understand this, check the following example:
setTimeout(() => console.log('first'), 0)
console.log('second')
You may think that first will be logged before second, but in fact it's second that will be logged first.
In your example the call stack is never empty, so setTimeout won't really work as expected.
You may wanna check this, it will give you a better idea about what's happening under the hood.
While(1) is an infinite while loop. I think that is the reason

Javascript: what is a callback?

In this article which I was referred to the following statement is made:
Callbacks are a way to make sure certain code doesn’t execute until other code has already finished execution.
The article then goes on to illustrate this with an example:
function doHomework(subject, callback) {
alert(`Starting my ${subject} homework.`);
callback();
}
doHomework('math', function() {
alert('Finished my homework');
After this the articles states:
As you’ll see, if you type the above code into your console you will get two alerts back to back: Your ‘starting homework’ alert, followed by your ‘finished homework’ alert.
The implication seems to be that by using a callback the desired order of code execution has been ensured. That is you start your homework before you finish it. However, I feel I may have misunderstood the whole point of the article and therefore still do not understand callbacks and asynchronous code because when I slow down the first part of the doHomework function using setTimeout() the code executes (or at least returns) in the opposite order:
function doHomework(subject, callback) {
setTimeout(function(){
console.log(`Starting my ${subject} homework.`);
}, 500);
callback();
}
doHomework('math', function() {
console.log('Finished my homework');
});
The result I get from that is:
steve#Dell ~/my-app $ node app.js
Finished my homework
Starting my math homework.
});
I am using node here (hence console.log() replaces alert()) but I do not think that is relevant.
It seems to me I have missed something quite fundamental and need to try and access what it is that I am trying to understand before I then try and understand it.
Any assistance on this journey would be greatly appreciated.
After getting great feedback I think the homework analogy was not helpful so I am now using the first code example in the article I referenced. The article gives this code:
function first(){
// Simulate a code delay
setTimeout( function(){
console.log(1);
}, 500 );
}
function second(){
console.log(2);
}
first();
second();
The above returns 2 then 1 in the console.
I tried (without success) to reverse the return order to 1 then 2 with this:
function first(callback){
setTimeout(function(){
console.log(1);
}, 500);
callback();
}
function second(){
console.log(2);
}
first(second);
The answer I got from Cleared (before it was edited) was to put the callback() inside the setTimeout() function. He used the homework example but here it is with this example:
function first(callback){
setTimeout(function(){
console.log(1);
callback();
}, 500);
}
function second(){
console.log(2);
}
first(second);
I think that is closer to what I am imagining the article was getting at. It seems to make sense although I guess the precise context of what you are doing and what you want to happen determine what is right or wrong.
In general, the call to the callback is not at the end of the function, but rather after you have done the important things.
So if I understand your question, the doHomework-function should start doing homework (which takes time, in this case 500ms), and then the homework is finished. So the important things in your case is the console.log('Starting my ${subject} homework.'); which "takes 500ms" (since this is the time you need to do the homework).
Therefore, you should put the call to the callback right after console.log('Starting my ${subject} homework.');, i.e.
function doHomework(subject, callback) {
setTimeout(function(){
console.log(`Starting my ${subject} homework.`);
callback();
}, 500);
}
doHomework('math', function() {
console.log('Finished my homework');
});
Generally, you would call the callback function when you are finished doing whatever it is you are doing.
So you have the code inside and outside your setTimeout function backwards.
function doHomework(subject, callback) {
console.log(`Starting my ${subject} homework.`);
setTimeout(function(){
console.log(`Finished my ${subject} homework.`);
callback();
}, 500);
}
What exactly is callback?
Callback meaning function-in-function like recursive.
Let me give you an example:
Every day we eating then sleeping. But in JS code, JS is an impatient language unlike PHP. This is the example code:
// Consuming 3s to eating(just an example, not really 3s)
function eating() {
setTimeout(function() {
console.log('Eating...');
}, 3000);
}
// Then go to sleep
function sleep() {
console.log('Z..Z..Z');
}
eating();
sleep();
But you sleep immediately after...(When we run the code it runs the sleep first then eating())
To assure that everything works in order, meaning you only go to bed when done eating. So we need the eating() to tell when it's done to start the sleep():
// Consuming 3s to eating(just an example, not really 3s)
function eating(callback) {
setTimeout(function() {
console.log('Eating...');
callback() // the function which will be proceeded after "Eating..."
}, 3000);
}
// Then go to sleep
function sleep() {
console.log('Z..Z..Z');
}
// call the function
eating(function() {
sleep();
});
Yeah! Right now I think you can use callback in your code!
Where you can see callback?
You can see it in every JQuery code:
$("#hide").click(function(){ //the click() function call the function inside it which is callback
$("p").hide();
});
$("#show").click(function(){
$("p").show();
});
Callbacks in Javascript are used in asynchronous programming, where you can't ensure that the code above is running before the code below, like loading files from a server asyncronous.
The problem is, that with normal sequential programming, you can not ensure, that the data you fetch is fully loaded when the programm is running (i.e. if you run the script, one time the variable could be setted, another time it could be undefined, cause async task is still running), so you set a callback function, which gets connected to different states, ie. success or error on ajax call. The difference to normal programming flow is, your programm does not stop till it has loaded the data (or in your case, the timeout doesnt pause your program, the code afterwards is computed and the timeout can run of anytime, if you dont use a fix value).
So, to ensure that your code will run when the needed logic finishes, you have to pass a callback function, which is executed when the needed state is fulfilled (i.e. success/error on loading tasks, or a timeout is "finished".
The homework example IMO isnt the best sample, cause it doesnt touch the real use cases, as it always "waits" 500ms.
In your example the problem is, your "callback" is out of the "asyncronous" part of code, so its executed directly after starting the timeout, even if the timeout still is "running". Maybe your thinking of SetTimeout is the problem, in my javascript beginnings I thought its more like "pause for 500ms", but its "execute the scoped code after waiting for 500ms out of the normal code flow"
Here are some more informations, I can recommend the whole page, even if your not javascript noob ;)
https://javascript.info/callbacks

Javascript Chrome console while

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.

Real asynchronous javascript function

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

Javascript execution order with setTimeout()

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 ;)

Categories

Resources