-1

I need to loop through a series of setTimeout functions, iteratively changing the function argument and the timeout value.

As discussed here, setTimeout performs (apparently) oddly in a for loop when printing values. You can use let or define another function to resolve.

This works as expected: printing i every second

function doSetTimeout(i) {
    setTimeout(function() { console.log(i); }, i * 1000);
}

for (var i = 1; i <= 5; ++i)
    doSetTimeout(i);

This does not work as expected: printing i sequentially every second, five seconds, second, etc. Instead of 0, 1, 2, 3, 4, it logs 4, 0, 2, 1, 3 in the browser console.

times = [1,5,1,5];
function doSetTimeout(i) {
    setTimeout(function() { console.log(i); }, times[i] * 1000);
}

for (var i = 0; i <= 4; ++i)
    doSetTimeout(i);

I've experimented with using let and an anonymous function and also not been successful.

RyGuy
  • 305
  • 4
  • 12
  • 1
    your `times` array has indexes from 0 to 4, so you should rather iterate like that: `for (var i = 0; i < 4; ++i)` – Joel Oct 14 '19 at 16:52
  • Change **var** to **let** This is drawback for var variable . Read difference between var and let then you ll come to know. If you want to use var then use **self invoking fun** to preserve value of **I** – vipul patel Oct 15 '19 at 15:19
  • @Joel, thank you. Corrected, my apologies for not putting together a good example, however, problem remains. If you copy that chunk into the browser console (atleast chrome or firefox)it returns 4, 0, 2, 1, 3, not 0, 1, 2, 3, 4. – RyGuy Oct 15 '19 at 15:19
  • @vipulpatel thanks, that may be the key but as I've mentioned, I couldn't get it to work with let either. Can you edit the code I provided? – RyGuy Oct 15 '19 at 15:23
  • @RyGuy , i have answered. Put given code in you doSetTimeout method – vipul patel Oct 15 '19 at 15:35

3 Answers3

0

Put below code in your dosetTimeout method : As i mentioned in comment

// capture the current state of 'i' // by invoking a function with its current value

(function(i) {
        setTimeout(function() { console.log(i); }, times[i] * 1000)
})(i);
vipul patel
  • 668
  • 4
  • 7
  • Thanks @vipulpatel, I'm still getting an unordered list. Perhaps you could provide a full working code example? – RyGuy Oct 15 '19 at 15:38
  • It prints unordered because set timeoit gets called after time[i] * 1000. Noe first 1*1000 and at last 5*1000 gets called. So orderlist changed. – vipul patel Oct 15 '19 at 15:46
0

I coded a quick solution based on your example.

var i = 0;
var times = [1,5,1,5];

function wait(milleseconds) {
       return new Promise(resolve => setTimeout(resolve, milleseconds))
}

async function myLoop (times,i) {
    await wait(times[i]*1000);
  i++;
  alert('HI');
  if(i<times.length)
  myLoop(times,i);
}

myLoop(times,i);
0

I failed to realize that I had to add the previous times to the total to get the sequential waits. This works:

previous = 0;
times = [1000,5000,1000,5000];

function doSetTimeout(i) {
    setTimeout(function() { console.log(i); }, times[i] + previous);
    previous += times[i]
}

for (var i = 0; i <= 3; ++i)
    doSetTimeout(i);
RyGuy
  • 305
  • 4
  • 12