Reputation: 85
I'm dealing with the closure issue right now and I need a little help on the topic: Using this code for my training:
for (var i = 1; i <= 10; i++) {
setTimeout(function(j) {
console.log(j);
}(i), 1000);
}
This solution timeouts for a second and then prints 1-10 in ascending order (as expected). Now, I want it to print j once every second:
1 (second passed...)
2 (second passed...)
3 (second passed...)
etc..
How can I make this happen without changing the formation of the loop?
Thanks in advance
Upvotes: 1
Views: 80
Reputation: 2179
Alongside RGraham's answer, I'd like to point out that when learning javascript, you should try to avoid using function expressions - they make code confusing to read.
Here's what your initial code looks like, without a function expression:
for (var i = 1; i <= 10; i++) {
setTimeout(doSomething(i), 1000);
}
function doSomething(i) {
console.log(i);
}
Or an even clearer representation:
for (var i = 1; i <= 10; i++) {
var k = doSomething(i);
// doSomething doesn't explicitly return anything, so k === undefined
setTimeout(k, 1000);
}
function doSomething(i) {
console.log(i);
}
Also, as I mentioned in my comment, your problem isn't really related to your closure attempt, but rather the way asynchronous operations work in Javascript. The most commonly used ways to sequence asynchronous operations are the continuation passing style/callbacks and promises.
Upvotes: 1
Reputation: 85
Thanks RGraham for the solution:
for (var i = 1; i <= 10; i++)(function (j) {
setTimeout(function () {
console.log(j)
}, 1000*j);
})(i);
Upvotes: 1
Reputation: 78535
setTimeout
expects a function to be able to execute. You need to return a function and also, seeing as your setTimeout
calls will occur one after another, you'll need to delay them
for (var i = 1; i <= 10; i++) {
setTimeout(function(j) {
return function() {
console.log(j);
}
}(i), 1000 * i); // Delay
}
That's without changing the formation of the loop. Although your best solution is to not use a for loop, but chain setTimeout
calls instead:
var i = 0;
function start() {
setTimeout(function() {
i++;
console.log(i);
// If we haven't reached our limit, start again
if(i < 10) start();
}, 1000);
}
start();
Upvotes: 3