3

I have multiple bulbs in one array. I'm trying to turn on and off the bulbs one by one. Each bulb should be turned ON for 1 second (one by one) and then all bulbs should be OFF for 2 seconds.

But in the below code, the output is not in the expected order. Seems like the inner setTimeout() does not follow the delay time of the outer one.

var array = [1, 2, 3, 4, 5, 6];
for (let i = 0; i < array.length; i++) {
  setTimeout(function() {
    console.log(i + " is on");
    setTimeout(function() {
      console.log(i + " is off");
    }, i * 1000);
  }, i * 3000);
}

I do not have to use setTimeout() here (if there's a better alternative).

Any idea will be appreciated.

FZs
  • 16,581
  • 13
  • 41
  • 50
Jing Fan
  • 63
  • 5

1 Answers1

3

Your nested timeout (off) will be set only when its "parent" timeout (on) fires.

That way, your off-timeouts' times are added to on-timeouts times (i * 3000 + i * 1000):

0*3000 + 0*1000 =     0
1*3000 + 1*1000 =  4000
2*3000 + 2*1000 =  8000
3*3000 + 3*1000 = 12000
4*3000 + 4*1000 = 16000
5*3000 + 5*1000 = 20000

If you compare these values to the on-timeouts, you get:

ON  0     0
OFF 0     0
ON  1  3000
OFF 1  4000
ON  2  6000
OFF 2  8000
ON  3  9000
OFF 3 12000
ON  4 12000
ON  5 15000
OFF 4 16000
OFF 5 20000

Therefore, there's no need for i * in case of off-timeouts.

var array = [1, 2, 3, 4, 5, 6];
for (let i = 0; i < array.length; i++) {
  setTimeout(function() {
    console.log(i + " is on");
    setTimeout(function() {
      console.log(i + " is off");
    }, 1000);
  }, i * 3000);
}

Also, it is better to avoid nested timeouts if possible, because they add up their delays. Instead, create them with their time added.

Like this:

var array = [1, 2, 3, 4, 5, 6];
for (let i = 0; i < array.length; i++) {
  setTimeout(function() {
    console.log(i + " is on");
  }, i * 3000);
  setTimeout(function() {
    console.log(i + " is off");
  }, i * 3000 + 1000);
}
FZs
  • 16,581
  • 13
  • 41
  • 50