0

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:

Javascript console output

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?

chuckx
  • 6,484
  • 1
  • 22
  • 23
zcahfg2
  • 861
  • 1
  • 12
  • 27
  • 1
    It did log it 5 times. That's why the console shows a 5 inna blue circle beside `hello`. When the same string is logged several times in a row the console groups the duplicates.It only should print one timerid, the last one, since you're not actually logging the timerid, you only see the one printed by the P step of the REPL. – Paul Jun 09 '18 at 06:06
  • 2
    Possible duplicate of [How do I add a delay in a JavaScript loop?](https://stackoverflow.com/questions/3583724/how-do-i-add-a-delay-in-a-javascript-loop) – Hassan Imam Jun 09 '18 at 06:16
  • 10920 is the result of the *last expression evaluated* (the timer ID in this case) from executing the code fragment. The "hello" (5 of them) is the console output when the timer is invoked. Since the timeout is 100 milliseconds (1/10th of a second), I don't know know why such would be expected before the loop terminates.. – user2864740 Jun 09 '18 at 06:22

3 Answers3

2

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
chuckx
  • 6,484
  • 1
  • 22
  • 23
1

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.

AkiraMiura
  • 94
  • 2
  • 6
  • "Synchronous program execution is somewhat similar to the above. Your program is executed line by line, one line at a time. Each time a function is called, program execution waits until that function returns before continuing to the next line of code.", I see thank you, I understood why ID "Hello" ID "Hello" is not possible in the original code above. – zcahfg2 Jun 09 '18 at 06:25
  • If I change the delay to 0 ms instead, then setTimeout is doesn't delay the code at all. So in this case, why is there no interleaving of ID and hello at all? With the delay being 0 it still logs all timer ID first and then print hello. for (var i = 1; i <= 5; i++) { console.log(setTimeout(function() { console.log('hello'); }, 0)); } – zcahfg2 Jun 09 '18 at 06:28
1

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);
}
Elon Musk
  • 354
  • 2
  • 5
  • 15