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);
How do I add a delay in a JavaScript loop?
The setTimeout()
function is non-blocking and will return immediately. Therefore your loop will iterate very quickly and it will initiate 3-second timeout triggers one after the other in quick succession. That is why your first alerts pops up after 3 seconds, and all the rest follow in succession without any delay.
You may want to use something like this instead:
var i = 1; // set your counter to 1
function myLoop() { // create a loop function setTimeout(function() { // call a 3s setTimeout when the loop is called console.log('hello'); // your code here i++; // increment the counter if (i < 10) { // if the counter < 10, call the loop function myLoop(); // .. again which will trigger another } // .. setTimeout() }, 3000)}
myLoop(); // start 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);
}
For loop with setTimeout?
The simplest way is to just use a different delay in each call of setTimeout
let counter = 1
for (...){
setTimeout(function() { }, 3000 * counter++);
}
Since Object.entries returns an Array, we could also use Arrray.entries to get a iteration counter in the for statement.
queries = {
"info": {
"query": "SELECT ..."
},
"info2": {
"query": "INSERT ..."
},
"infoN": {
"query": "DELETE ..."
}
}
for (let [counter, [key, value]] of Object.entries(queries).entries()) {
const delay = (counter + 1) * 1000
setTimeout(() => {
console.log({
counter,
delay,
key,
value
})
}, delay)
}
setTimeout executes after for loop in javascript
JS is sync. So all sync code is done first, and all async go in separate thread and they may finish earlier but they have to wait until all sync code is done.
setTimeout(function(){
console.log('setTimeout executes');
},1000); // this function go async in separate thread
for(var i=0;i<10000;i++){
console.log('inside for loop'); // sync
}
console.log('after For Loop'); // sync
// after all sync code async result will be called
// console.log('setTimeout executes'); will happen here
If you want full picture of how JS engines works read this. It is very basic and helps a lot.
setTimeOut' calls in JavaScript 'for' loops, why do they fail?
You are correct that lexical scoping is the cause of this behavior. When the timer functions run (which will be after the currently running code completes), they attempt to resolve i
and they must look up the scope chain to find it. Because of lexical scoping, i
exists only once in the scope chain (one scope higher than the timer functions) and, at that point, i
is 6
because, at that point, the loop has terminated.
The var
keyword causes variables in JavaScript to have either function or Global scope (based on where that declaration is). In your code, var i
causes the i
variable to exist Globally (because your code is not inside of a function) and each timer function must resolve that same, single i
when they eventually run. Since the timer functions won't run until the loop is done, i
is at its last value (6) that the loop caused it to be.
Change var i
to let i
to create block scope for i
to solve the problem.
let
creates block scope for the variable. Upon each iteration of the loop, you enter the loop block again and a separate scope is created for i
that each timer function gets to itself.
for (let i = 1; i <= 5; i++) { setTimeout(function() { console.log(i); }, 1000*i);}
Related Topics
How to Use JavaScript Variables in Ruby
Access Parent's Parent from JavaScript Object
Wait for Multiple Promises to Finish
Fire Jquery Event on Div Change
Rails 4 - Gmaps4Rails - Map Won't Render
How to Remove a Character from a String Using JavaScript
How to Display Multiple Google Maps Per Page with API V3
Protractor E2E Test Case for Downloading PDF File
Time Conversion Between Ruby on Rails and JavaScript Vice Versa
Ruby Hash Equivalent of JavaScript's Object Initializer Es6 Shorthand
Remove Duplicates Form an Array
How Might I Extract the Property Values of a JavaScript Object into an Array
Ruby Methods Within JavaScript Within Haml
Error: Require() of Es Modules Is Not Supported When Importing Node-Fetch
JavaScript Getter for All Properties
In R, How to Display Value on the Links/Paths of Sankey Graph
What Is the "Best" Way to Get and Set a Single Cookie Value Using JavaScript