Why does setTimeout only print once in a loop? - javascript

From this document, I understand that setTimeout returns an ID value of the timer.
But when I run this code:
for (var i = 1; i <= 5; i++) {
setTimeout(function() { console.log('hello'); }, 100);
}
I get the following in the console tab:
i.e. It printed the timer ID once and then 5 consecutive 'hello' instances.
Shouldn't the output have timerID, hello, timerID, hello, .... instead?
Why does setTimeout only print its ID once even if it is in the loop?

What you're seeing is due to the REPL (Read-Eval-Print Loop) nature of the Javascript console.
You're expecting to see the result of all the setTimeout() calls from each iteration of the loop. However, after finishing a set of statements, the JS console only prints out the return value of the most recently executed statement.
A simple display of this behavior:
Note: In these examples I'm depicting the JS console input/output instead of including executable code blocks, since the behavior being discussed is specific to interactively using the console.
> x = 4;
<- 4
> y = 5;
<- 5
> x; y;
<- 5
In the last command there are two statements, only the value of the last is printed.
If you want to print out the id's of each setTimeout() call, you just have to explicitly perform the logging action:
> for (var i = 1; i <= 5; i++) {
console.log(setTimeout(function() { console.log('hello'); }, 100));
}
596
597
598
599
600
<- undefined
5 hello
Above you see:
the 5 outputs from the immediately executed console.log(setTimeout(...)) statements
the undefined return value of the last console.log(setTimeout(...)) statement
the grouped output from the 5 delayed console.log('hello') statements

The reason why this is happening is because synchronous code. When you run the for loop, it is executing the setTimeout() 5 times and so you get the ID, and after 0.1 seconds (100 MS) it then executes its code. If you want to get it how you predicted (ID "Hello" ID "Hello" ... ) you would have to use await and an asynchronous function.

The function setTimeOut returns a value, so it is not displayed in the console, unless you assign a variable to it and then output the variable.
for (var i = 1; i <= 5; i++) {
let delay = setTimeout(function() { console.log(delay,'hello'); }, 100);
}

Related

Do While Loop where I console.log a phrase is the integer between 10-0?

I'm attempting to make a function wherein I console.log a phrase when the number is between 0-10.
I'm getting it to print out the phrase 10 times, but to get it to pass the testing platform, I need to print it out when the number is 0, and it's not passing.
function doWhileLoop(num) {
var i = 0;
function incrementVariable() {
i++
return i;
}
do {
console.log(i, "I run once regardless.");
}
while (incrementVariable() <= 9);
}
doWhileLoop(10);
Only print when incrementVariable() is less than the variable received:
function doWhileLoop(num) {
var i = 0;
function incrementVariable() {
i++
return i;
}
do {
console.log("I run once regardless.");
}
while(incrementVariable() <= num);
}
The point is that the loop condition must muse the parameter that is passed to the doWhileLoop function (while(incrementVariable() <= num)). And I guess the exercise is trying to show you that the code inside the do block will always run at least once, even if the condition in the while is false. So the following code runs once:
do {
console.log("I run once regardless.");
}
while(false);
Making this not count past 9
function doWhileLoop(num) {
if(num>9) {
num = 9;
}
var i = 0;
function incrementVariable() {
i++
return i;
}
do {
console.log("I run once regardless.");
}
while(incrementVariable() <= num);
}
Note, it is not clear to me whether you want it to print 10 times either 0 or 10 cannot be included. If you want it to print 0..10 that would actually be 11 times. So adjust the examples below as appropriate.
Note that while troubleshooting, it is helpful to print the value i, as I did in the examples below. When the program works as expected, you can then remove i from your console.log before for your final submission.
I also print out the final value of i when the loop is exited.
This is a god point of comparison for understanding how the loops, and the incrementation of values work in each case. It's also good to know how these loops leave variables that may be accessed later in a program, and serves as a comparison to the values printed.
The first two examples do not use a separate function just to increment, since incrementation itself is a function, and is built into the language. It also highlights how two variations the language provides for incrementing can be exploited in useful ways to control endpoint conditions such as this.
In all cases I consistently used i < num so the comparisons would hold.
Depending on your requirements, this could also be i < num+1 (equivalent to i <= num), or i < num-1. Adjusting this will increase or decrease the last/highest value of i that is printed, (and the value i has after the loop ends).
++i prints 10 times: when i is 0..9.
i === 10 when the loop ends.
(using i <= num would print 0..10 and exit with value 11)
function doWhileLoop(num) {
let i = 0;
do {
console.log(i, "I run once regardless. ");
}
while (++i < num);
console.log("Final value of i:", i);
}
doWhileLoop(10);
For comparison, this version,
i++ prints 11 times: when i is 0..10.
i === 11 when the loop ends.
(using i < num+1 would print 0..9 and exit with value 10)
function doWhileLoop(num) {
let i = 0;
do {
console.log(i, "I run once regardless. ");
}
while (i++ < num);
console.log("Final value of i:", i);
}
doWhileLoop(10);
The difference between ++i and i++ is that:
++i the increments i first, then uses new value to determine whether to run the loop again or not.
i++ determines whether or not to run the loop again first, based on the value i already has (and printed), then it increments i afterwards, but before runs the loop again (or before it exits, if the loop is not be be run again).
In your code, incrementVariable() acts exactly like my ++i example above, because the incrementVariable() function call is executed before the while comparison is made.
Another solution would be to use an if-then to constrain your print statement.
This version prints 10 times: when i is 0..9.
i === 10 when the loop exits.
(In this scenario you can control the final value of the loop, and the number of times the loop is run, independent from the values that are printed.)
function doWhileLoop(num) {
var i = 0;
function incrementVariable() {
i++
return i;
}
do {
if (i < num) {
console.log(i, "I run once regardless.");
}
}
while (incrementVariable() < num);
console.log("Final value of i:", i);
}
doWhileLoop(10);

How to continuously .replace() words inside editable <div> with JavaScript?

I'm trying to create a simple IDE, all it will do is colour code certain syntax. Right now I'm trying to figure out how to replace something like var with <span id="var">var</span>. The .replace() works when the page firsts loads, but not after you start typing, even though it's running on an interval.
The live code is here codepen.io/Alanay/pen/goLgdx
Here's just the JS:
document.getElementsByTagName('div')[0].contentEditable = 'true';
function syntax() {
var div = document.getElementsByTagName('div')[0].innerHTML;
var res = div.replace("IDE", "Test");
document.getElementsByTagName('div')[0].innerHTML = res;
}
setInterval(syntax(), 500)
Let's I will explain why it hadn't worked with your code.
The setInterval method takes 2 params, the function you want to run and delay of next execution in milliseconds.
When you call the function with parentheses like syntax() it will give you the function output i.e
In below code the sum function does summation of 2 numbers and showing it in span element.
Basically return statement stops function execution and gives output.
function sum(a, b) {
return a + b
}
// will print 3;
let sumDiv = document.getElementById('sum');
sumDiv.innerHTML = sum(1, 2);
The sum is <span id='sum'></span>
If you don't have return statement, the function automatically will return undefined.
In the below code I am doing addition of 2 numbers, but not returning them and function returns undefined.
function sum(a, b) {
a + b
}
// will print 3;
let sumDiv = document.getElementById('sum');
sumDiv.innerHTML = sum(1, 2);
The sum is <span id='sum'></span>
Let's return to setInterval and to our syntax function.
When you call setInterval(syntax(), 500), your syntax() function executes and returns undefined as setInterval first argument function.
You just need to pass your syntax function without calling.
setInterval(syntax, 500)
The above code will work, because you are just passing your function to be executed each 500 milliseconds, instead of it's returned value which is undefined and will cause wrong behavior.
You can read more about undefined type and return statement here and here respectively. They are very important parts of JavaScript and I suggest you to spend little bit time to read about them.
your syntax is wrong. Just set it to setInterval(functionname_without_paranthesis, time_in_ms).
Just set it to setInterval(syntax, 500)

What is the logic behind this double function call with recursion?

Where I currently have the console logs, countdown seems to count down from 10 to 1 (this makes sense) but then after this, way seems to add 15 to the final result of countdown 9 times, but for this to happen, I'd imagine that after each countdown loop, way is called, but that each keeps track of its own value? Any clarification about the Why and When of this logic would be helpful - Thanks!
var countdown = function(value) {
value = value - 1;
if (value == 0) {
return value;
}
console.log("loop 1 " + value);
return way(countdown(value));
};
function way(value) {
value = value + 15;
console.log(value);
return value;
}
countdown(10);
As commented above value is a local variable in either function and thus always bound to the scope of either function. It doesn't actually contribute to confusion aside from expecting too much complexity there. ;)
The behaviour arises from countdown() being called recursively and calling way() has to wait until recursive calls for countdown() are returning. But that's not happening until countdown()'s recursion has stopped at value 0 to be returned eventually. After that countdown() isn't invoked ever again, but since countdown() was invoked recursively and this is bubbling up through all invocations of countdown() there are multiple calls for way() with the result returned from the countdown() called at end which in turn was calling way() with result of countdown() etc. ... ok, got a bit confused here myself.
Since value isn't required to be that complex it might help to eliminate it for reducing code:
function countdown(value) {
if ( value == 1 ) { return 0; } // bail out condition
console.log("loop 1 " + value)
return way( countdown( value - 1 ) );
};
function way( value ) {
console.log(value);
return value + 15;
}
countdown(10);
way() is of no relevance to the recursion and thus might be substituted:
function countdown(value) {
if ( value == 1 ) { return 0; } // bail out condition
console.log("loop 1 " + value)
return countdown( value - 1 ) + 15;
};
countdown(10);
Due to recursion this code is diving into stack 9 frames deep. And then it is bubbling up stack returning the result of every passed frame increased by another 15 prior to bubbling up further on.
So actually, there is only one recursion.
At first, the code starts executing your first call to countdown with argument value=10
Stack: []
Execute countdown(10)
Stack: [countdown(10)]
Then execute way(countdown(9)), and to execute this, JS first evaluates countdown(9)
Stack: [countdown(10), countdown(9), ] and so on, you can imagine, until you reach countdown(0), then start popping out from the stack call.
First stack call resolved, countdown(0) = 0, then call way(0), the console logs 0+15, then countdown(0) eventually returns 15, then pop from stack countdown(1) which is equal to way(countdown(0)), which is way(15), then prints out 30, and so on...
Hope this is clear enough
In order to understand this recursive code, it's easiest to follow the program counter:
function way (value) {
value=value +15
console.log(value)
return value
}
countdown = function(value) {
value = value-1
if (value == 0) {
return value;
}
console.log("loop 1 " + value)
return way(
countdown(value));
};
countdown(10);
Start countdown with 10
value > 0 so run way(countdown(9)) //note: countdown is executed first.
Countdown runs with 9
value > 0 so run way(countdown(8)) //note: countdown is executed first.
...
...
...
value == 0, return 0 (in countdown): execute way
way returns 0 + 15
way returns 15 + 15
way .... etc.
As fora clarification why this logic would be helpful; I think there is a lesson to be learned here.
Basically there are 2 relevant function-call positions when applying recursion:
positioned before recursive call
positioned after recursive call
I will leave it as an exercise of why this has any relevance.

javascript w/ jquery loop

im having a problem with my code, i have to make a loop, that each it loops, have to change add a class/change the color of something for just a while. i tried with a for and it didnt work, then i tried something like a loop using setinterval and it works better but still have something that is not working, it just adds the class/or toggle in that case first 1 element, and then maybe 2, then 3,etc and not 1 by 1 thanks
function runp(patron){
var x = 0;
var intervalID = setInterval(function () {
$("#container"+patron[x]).toggle(1).delay(1000).toggle(1).delay(1000);
if (++x === 20) {
window.clearInterval(intervalID);
}
}, 2000);
}
this is what i have: https://jsfiddle.net/dt8kxebg/
and this is what im trying to replicate: https://jsfiddle.net/jf0opams/
I think your problem is that you execute the runp() several times, because it is inside of a for loop. You should rather invoke the function just once after the loop, when your patron[] array is filled with random numbers (1-4).
The problem happens, because the for loop is super fast (few millisecs) filling your array with 20 random numbers. So you have invoked the animation/toggling function 20 times. This on/off behaviour takes 2 seconds and happens 20 times almost at the same time. You can see in my code in the browser console what the console.log() output to understand the behaviour better.
function start(patron, patronl){
while (patron.length<20){
patron.push(rand(1,4));
console.log('start: '+patron.length);
//runp(patron, patron.length);//old place
//readp(patron,//
}
runp(patron);//new place
}
function runp(patron, iteration){
var x = 0;
var intervalID = setInterval(function () {
$("#container"+patron[x]).toggle(1).delay(1000).toggle(1).delay(1000);
//see how 20 outputs come at once, if runp() is inside for loop
console.log('togglewait: '+x, 'start: '+iteration);
if (++x === 20) {
window.clearInterval(intervalID);
}
}, 2000);
}

How to count how many times a line of code is executed in Chrome Dev Tools?

How could I run a simple diagnostic to check how many times a particular line of code is executed (passed by) in Chrome Dev Tools? Obviously without counting it myself with a debugging breakpoint and without writing any redundant code inside the codebase.
I want to do it on a regular basis, that is - I do something on the interface to call for a for (f.ex) cycle and I want to see imediately how many times a particular line was executed, then press again and see a new result again (maybe a reset inbetween could be tolerated)
You could use console.count, it will log how many times it was called with a given label:
console.count('Some Identifier')
If you don't want your log filled up with "foo: 19" and just want a total instead, you could create your own count function that only returns the total when requested:
var counter = (function() {
var counters = {};
return {
count: function(label) {
counters[label] = counters[label] ? counters[label] + 1 : 1;
return this;
},
total: function(label) {
return +counters[label];
}
}
})();
for (var i = 0; i < 10; i++) {
counter.count('bar');
}
console.log("bar called", counter.total('bar'), "times");

Categories