0
for (var i = 1; i <= 4; i++) {
  (function (j) {
    setTimeout(function () {
      console.log(j);
    }, j * 1000);
  })(i);
}

In the above code my understanding is that each iteration of the for loop, the time before the IIFE executes increases since it's multiplying the current item in the loop by 1000; it will be 1 second, 2 seconds, 3 seconds, then 4 seconds before it executes. But when I try running this in the Chrome developer tools console it doesn't seem like the amount of time between 1, 2, 3, and 4 being printed is increasing at all. It's definitely not 4 seconds between 3 and 4 being printed.

To compare try running:

(function (j) {
    setTimeout(function () {
      console.log(j);
    }, j * 1000);
 })(4);

Am I missing something here?

nCardot
  • 5,992
  • 6
  • 47
  • 83
  • 1
    `setTimeout` doesn’t wait synchronously. That’s the reason _why_ the delay is multiplied by the index — otherwise all callbacks would happen at the same time. – Sebastian Simon Aug 14 '21 at 17:30
  • 1
    Related: [How do I add a delay in a JavaScript loop?](/q/3583724/4642212). – Sebastian Simon Aug 14 '21 at 17:37
  • 1
    Loop completes in just a few ms so all those delays are based on just about the same start instant in time when the loop runs.... now + 0, now +1sec, now +2sec etc.... – charlietfl Aug 14 '21 at 17:39

2 Answers2

1

You seem to have a fundamental misunderstanding that the loop or the IIFE will have a delay each iteration based on the setTimeout but that is not the case

Add some elapsed time logging to your scenario and you will realize that the IIFE are invoked every iteration of the loop with no delay. Thus each of the setTimeout has basically the same start time

let sTime = performance.now();

for (var i = 1; i <= 4; i++) {
  (function (j) {
     const eTime = performance.now()
    console.log(`IIFE i=${i} , elapsed = ${eTime-sTime}`)
    setTimeout(function () {
      const eTime = performance.now() 
      console.log(`Timeout i=${j} , elapsed = ${eTime-sTime}`);
    }, j * 1000);
  })(i);
}
charlietfl
  • 170,828
  • 13
  • 121
  • 150
1

Your for loop doesn't wait for the timeout to finish.

The first iteration setTimeout wait 1 sec. The second iteration 2 sec., etc. This is why the console.logs are 1 second apart.

If you want between the console.log to be 1, 2, 3 and 4 seconds apart you need to increase the timeout by the sum of the digits 1 to n.

   // 1st log at 1 sec.
   //  -> 2 seconds later 
   // 2nd log at 3 sec. (1 + 2) 
   //  -> 3 seconds later
   // 3rd log at 6 sec. (1 + 2 + 3) 
   //  -> 4 seconds later 
   // 4th log at 10 sec. (1 + 2 + 3 + 4)

function sumOfDigits(n) {
   return (n * (n+1)) / 2;
}

for (var i = 1; i <= 4; i++) {
  (function (j) {
    setTimeout(function () {
      console.log(j);
    }, sumOfDigits(j) * 1000);
  })(i);
}
Erwin van Hoof
  • 957
  • 5
  • 17