0

I want to call a function in a cycle with setTimeout(), and also pass the counter as a parameter. Here's what I tried:

<!DOCTYPE html>
<html><body>

<button onclick="timed1()">Display alerts</button>

<script>
function timed1() {
 for (i=1; i<4; i++){
  setTimeout(
     (function(i){ alert(i) })(i), 1000*i
   );
 }
}
</script>

</body></html>

Function calls are done with correct values, but immediately instead of the intervals I wanted. I have read this and this SO questions but unfortunately don't see yet what should I change in my case.

2
  • man that line is so unreadable Commented Feb 7, 2018 at 21:08
  • So you are executing the function and assigning what it returns to the timeout. Commented Feb 7, 2018 at 21:09

4 Answers 4

1

You can use let here if you want to bind different values of i to the setTimeout function

function timed1() {
    for (let i=1; i<4; i++){
      setTimeout(function() { 
          alert(i) 
      }, 1000*i)
    }
}
timed1()

Sign up to request clarification or add additional context in comments.

Comments

1

You're swimming on IIFE (Immediately Invoked Function Expression).

You're calling your function immediately.

setTimeout(
   (function(i){ alert(i) })(i), 1000*i
);                           ^

The scope of your variable i is open, you need to use let keyword.

for (i = 1; i < 4; i++) {
     ^

Look at this code snippet

function timed1() {
  for (let i = 1; i < 4; i++) {
    setTimeout(
      function() {
        alert(i)
      }, 1000 * i);
  }
}
<button onclick="timed1()">Display alerts</button>

1 Comment

thank you for the detailed explanation, I appreciate it!
1

The setTimeout function allows you to pass arguments to the callback function, like so:

function timed1() {
  for (i=1; i<4; i++){
    setTimeout(alert, 1000 * i, i);
  }
}

timed1()

Any arguments after the time are passed along to the callback.

1 Comment

ah, that's very neat! didn't think about passing the arguments that way, thank you!
1

The expression (function(i){ alert(i) })(i) does not return a function for setTimeout to call. If you're going the IIFE way, make sure to return a new function from it:

setTimeout((function(i) {
    return function() {
        alert(i);
    };
})(i), 1000 * i);

With ES2015+ a far better readable equivalent can be realized:

for (let i = 1; i < 4; i++) {
    setTimeout(() => alert(i), 1000 * i);
}

3 Comments

thank you @Jeffrey! (in my case, I'll take mehulmpt's solution for its easier readability, but I learned important piece from yours)
That's fine :) I have added a more readable equivalent, just for fun.
awesome, thanks! I'm only starting to learn arrow functions :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.