Settimeout in For-Loop Does Not Print Consecutive Values

setTimeout in for-loop does not print consecutive values

You have to arrange for a distinct copy of "i" to be present for each of the timeout functions.

function doSetTimeout(i) {
setTimeout(function() { alert(i); }, 100);
}

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

If you don't do something like this (and there are other variations on this same idea), then each of the timer handler functions will share the same variable "i". When the loop is finished, what's the value of "i"? It's 3! By using an intermediating function, a copy of the value of the variable is made. Since the timeout handler is created in the context of that copy, it has its own private "i" to use.

edit — there have been a couple of comments over time in which some confusion was evident over the fact that setting up a few timeouts causes the handlers to all fire at the same time. It's important to understand that the process of setting up the timer — the calls to setTimeout() — take almost no time at all. That is, telling the system, "Please call this function after 1000 milliseconds" will return almost immediately, as the process of installing the timeout request in the timer queue is very fast.

Thus, if a succession of timeout requests is made, as is the case in the code in the OP and in my answer, and the time delay value is the same for each one, then once that amount of time has elapsed all the timer handlers will be called one after another in rapid succession.

If what you need is for the handlers to be called at intervals, you can either use setInterval(), which is called exactly like setTimeout() but which will fire more than once after repeated delays of the requested amount, or instead you can establish the timeouts and multiply the time value by your iteration counter. That is, to modify my example code:

function doScaledTimeout(i) {
setTimeout(function() {
alert(i);
}, i * 5000);
}

(With a 100 millisecond timeout, the effect won't be very obvious, so I bumped the number up to 5000.) The value of i is multiplied by the base delay value, so calling that 5 times in a loop will result in delays of 5 seconds, 10 seconds, 15 seconds, 20 seconds, and 25 seconds.

Update

Here in 2018, there is a simpler alternative. With the new ability to declare variables in scopes more narrow than functions, the original code would work if so modified:

for (let i = 1; i <= 2; i++) {
setTimeout(function() { alert(i) }, 100);
}

The let declaration, unlike var, will itself cause there to be a distinct i for each iteration of the loop.

JavaScript : For loop with timeout

You can work that out with simple math :

for (var i=0;i<=10;i++) {
(function(ind) {
setTimeout(function(){console.log(ind);}, 1000 + (3000 * ind));
})(i);
}

1000ms : 0

4000ms : 1

7000ms : 2

10000ms : 3

13000ms : 4

...



Following the comments

It seem that your request is a bit blurry. if you want to do something after the last timeout, you can set a limit and compare the current index :

var limit = 10
for (var i=0;i<=limit;i++) {
(function(ind) {
setTimeout(function(){
console.log(ind);
if(ind === limit){
console.log('It was the last one');
}
}, 1000 + (3000 * ind));
})(i);
}

Fiddle : http://jsfiddle.net/Tn4A7/



I think I know what you want...

and it is to simply do

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

setTimeout does not print consecutive numbers because of closure

Wrap it in a self-executing closure:

for (var i = 0; i < 5; i++) (function(i) {
setTimeout(function() {
console.log(i)
}, 1000);
})(i);

Note: the argument to the function-expression to setTimeout is not being used, so I took that out. Also, it's not good to use global variables. Create variables using the var keyword.

You also don't need this.i; simply use i.

For loop does not work correctly because of setTimeout

Use let instead of var:

const sentence = "The quick brown fox jumps over the lazy dog.";

for (let i = 0; i < sentence.length; i++) {
setTimeout(() => {
console.log(
`The character at index ${i} is ${sentence.charAt(i)}`
);
}, (i + 1) * 100);
}

Another way could utilize the fact that setTimeout can pass arguments to the function that will be called:

const sentence = "The quick brown fox jumps over the lazy dog.";

for (var i = 0; i < sentence.length; i++) {
setTimeout((x) => {
console.log(
`The character at index ${x} is ${sentence.charAt(x)}`
);
}, (i + 1) * 100, i);
}

setTimeout in for loop (1 timeout then loop at once) (double loop)

The problem is in how the setTimeout works. It's not a sleep command where it stops the for loop. Rather, it is blazing through the initial for loop, and starting three timers at roughly the same time, to last for one second each. That means they also all end at about the same time.

You can get your desired outcome by doing something more like this (notice the i*delay for the timer on the setTimeout. That way your first timer is for 0ms, second for 1000ms, third for 2000ms, and you get the staggered results you're after.

var data = [

[

["data[0][0]"],

["data[0][1]"]

],

[

["data[1][0]"],

["data[1][1]"]

],

[

["data[2][0]"],

["data[2][1]"]

]

];

var delay = 1000;

function doSomething(i) {

setTimeout(function () {

for (let j = 0; j < data[i].length; j++) {

console.log(data[i][j]);

$('#result').html($('#result').html() + data[i][j]);

}

}, i*delay);

}

for (let i = 0; i < data.length; i++) {

doSomething(i);

}
    <script src="http://code.jquery.com/jquery-1.9.1.js"></script>

<div id="result"></div>

setTimeout not working inside of my for loop - skipping it completely

Rather than that, why not just set and interval, execute on the current array value until it's done, then clear it?

let ctr = 0, time = setInterval(function() {
let curitem = arr[ctr];
// do somethign with curitem
if (++ctr >= arr.length) clearInterval(time)
}, 5000);

Unable to iterate through timeout value using setTimeout in for loop

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);

Repeating setTimeout in a for loop

That loop will create 100 setTimeout that all run at virtually the same time since the loop will complete in a few milliseconds.

Multiply the duration by i to increment it so the durations will be multiples of 1000.

You need to use let instead of var to block scope i

for (let i = 0; i <= 100; i++) {
setTimeout(function() {
celsiusToFahrenheit(i);
}, 1000 * i);
}


Related Topics



Leave a reply



Submit