In this tutorial, you’ll see some issues related to using setTimeout inside for loop and how to work around such issues. You’ll start by understanding what a setTimeout method is used for in JavaScript.

Understanding setTimeout in JavaScript

setTimeout is used to fire a piece of code after the specified timers expires. Here is an example code to demonstrate setTimeout.

// setTimeout example 
setTimeout(function(){
    console.log('setTimeout fired afer 3 seconds');
}, 3000);

As shown in the above piece of code, the callback function is executed after the specified time interval expires.

setTimeout Inside For Loop

Now let’s see how a setTimeout executes inside a JavaScript for loop. Here is how the code looks:

// setTimeout inside a For loop
for(var i = 0;i < 5; i++){
    setTimeout(function(){
        console.log('count ', i);
    }, 3000);
}

Problem : When you execute the above piece of code, you will see the last value of i being printed each time on setTimeout callback execution. Here is the output of the above code:

count  5
count  5
count  5
count  5
count  5

Let’s try to understand what is really happening in the above piece of code. The setTimeout function callback isn’t triggered until the for loop execution has completed. When the for loop has finished executing the value of i is 5. Now when the setTimeout call begins to execute it uses the last set value of i which is 5. Hence 5 is printed in all the setTimeout callbacks.

Solution 1 : setTimeout Inside For Loop Using IIFE (Immediately Invoked Function Expression)

One solution to the above seen issue is to create a new scope for each setTimeout execution. You can use IIFE to create a new scope for each setTimeout callback without polluting the global scope. Simply wrap up the setTimeout code inside a IIFE. Here is how it looks:

// setTimeout inside for loop with IIFE Wrapper

for(var i = 0; i < 5; i++){
    (function(i){
        setTimeout(function(){
            console.log('value is ', i);
        }, 3000);
    })(i);
}

The above code when executed will print the following output in the browser console.

value is  0
value is  1
value is  2
value is  3
value is  4

You can even add a bit of delay between printing of the console log messages by dynamically increasing the setTimeout interval.

// setTimeout inside for loop with IIFE wrapper
for(var i = 0; i < 5; i++){
    (function(i){
        setTimeout(function(){
            console.log('value is ', i);
        }, 3000 * (i + 1));
    })(i);
}

Solution 2: setTimeout Inside For Loop Using let Keyword

Another way to solve the problem is using the ES6 let keyword inside the for loop. The let keyword creates a separate scope for each iteration making it possible to print the consecutive variable value. Here is how the code looks:

// setTimeout inside For loop Using let keyword
for(var i = 0;i < 5; i++){
    let k = i;
    setTimeout(function(){
        console.log('count ', k);
    }, 3000 * (k + 1));
}

Execute the above piece of code and you will be able to view the numbers from 0 to 4 printed in the browser console.

Wrapping It Up

In this tutorial, you learnt how to use setTimeout inside For in JavaScript. You saw the issue created when iterating setTimeout inside a loop and how to solve it using IIFE and let keyword.

Have you ever encountered this issue ? Did you use a different approach to solve it ? Do let us know your thoughts and suggestions in the comments below.