-1

I've got this Problem here, that this function is not working and I cant figure out why.. This function should count to 10 (in 10 seconds). For this purpose I'm using a for loop with setTimeout function - duration set to 1000ms.

It should go on and on for what i took the setInterval function.

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

setInterval(timer, 10000);

The Problem is, that it isnt working and I dont understand why ... I have found another working solution but would like to know the issue of this one. :)

epgrape
  • 41
  • 5
  • 4
    setTimeout and setInterval both expect a function. You properly gave setInterval a function, but you instead gave setTimeout undefined. – Kevin B Sep 11 '15 at 21:36
  • console.log doesn't return anything that'd be useful as the setTimeout callback. maybe you meant to do `setTimeout('console.log(i+1)', 1000)` (note the `'`-quotes)? – Marc B Sep 11 '15 at 21:37
  • 1
    @MarcB: Do not pass a string to `setTimeout`. – SLaks Sep 11 '15 at 21:38
  • oh i thought console,log() would be a legit function, so it isnt? – epgrape Sep 11 '15 at 21:38
  • @epgrape `console.log` is a function. `console.log(i+1)` is a function call, and it evaluates to `undefined`. – jrsala Sep 11 '15 at 21:40
  • KevinB and jrsala thank you guys :) – epgrape Sep 11 '15 at 21:42
  • `console.log` is a function, but that isn't what you're passing - you are passing the result of `console.log(i+1)`. `console.log(i+1)` is function call that returns `undefined` so you're passing `undefined` to `setTimeout()`. – jfriend00 Sep 11 '15 at 21:43
  • OP already has it figured out... Downvote... – Adam Buchanan Smith Sep 11 '15 at 21:45
  • @AdamBuchananSmith I dont know why you are downvoting, there is no answer "code" which i can give the "answer right" flag – epgrape Sep 11 '15 at 21:48
  • Reword your question so we don't waste our time, you are asking us to de-bug your code, then we give you good code, then you tell us its not what you want, make up your mind :) – Adam Buchanan Smith Sep 11 '15 at 21:52
  • @AdamBuchananSmith if you could read u would know that i didnt want any "other" working code. – epgrape Sep 11 '15 at 21:56
  • 1
    I can read this: Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers. See: How to create a Minimal, Complete, and Verifiable example. – Adam Buchanan Smith Sep 11 '15 at 22:02

3 Answers3

2

The reason that nothing appears to happen is the way that you use setTimeout. Instead of providing an event handler you are calling console.log and try to use the return value from that call as event handler.

The closest thing that would at least do something would be to make a function that calls console.log:

setTimeout(function(){ console.log(i+1) }, 1000);

However, you will notice that it will just log the value 11 ten times at once, every ten seconds, indefinitely.

Eventhough the loop counts from 0 to 9, you start a timeout in each iteration that will be triggered one second from when it was created. As all ten timeouts are created at the same time, they will be triggered at the same time. There isn't a separate variable i for each handler, so they will all show the value in the variable at the time that they are triggered, and as the loop has completed before any of them can be called they will all show the final value 10 + 1.

You are using both an interval and timeouts, you should use one or the other.

You can start timeouts in a loop, but then you should only do it once, not in an interval, and you should specify the time from start to when you want it to be triggered:

var time = 10;
for (var i = 1; i <= time; i++){
  setTimeout(function() { console.log('tick'); }, 1000 * i);
}

If you want to use the variable in the event handler, then you need to create a copy of the variable for each iteration:

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

You can use an interval, but then you don't have a loop, it's the interval that is the loop. Use clearInterval to stop it when you reach the end of the loop:

var i = 1, time = 10, handle;
function timer() {
  console.log(i);
  i++;
  if (i > time) clearInterval(handle);
}

handle = setInterval(timer, 1000);
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
0

First, it's not working because setTimeout call is wrong. Even if your setTimeout call worked, there's another issue here. Your code will actually print 11 every 10 seconds.

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

setInterval(timer, 10000);

Because, you have sequential setTimeout calls to be effected every second and you are forming a closure on the variable i.

You need to take care of the closure and calls must be done after the second has been printed.

function timer() {
    var p = Promise.resolve();
    for (var i = 0; i < 10; i++) {
        p = p.then(closure(i));
    }
}

function closure(i) {
    return (function () {
        return new Promise(function (resolve) {
            setTimeout(function () {
                document.getElementById('results').innerHTML = (i + 1) + '\n';
                resolve();
            }, 1000);
        })
    });
}

timer();
setInterval(timer, 10000);
<pre id="results"></pre>
MinusFour
  • 13,913
  • 3
  • 30
  • 39
-1

When I run your code in the Firebug debugger, I see:

TypeError: can't convert console.log(...) to string

I added a comment to your code about that error:

function timer() {
  var time=10;
  for(i=0; i<time; i++){
  // The source of error is the line below
  // Type error: setTimeout needs a function as first argument!
   setTimeout(console.log(i+1), 1000);
  }
}

setInterval(timer, 10000);

A corrected version might be

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

setInterval(timer, 10000);

However, the above change fixes the type error but not the logic.

You probably wanted to do this:

var counter = 0;

var count = function() {
  console.log(++counter);
  if (counter >= 10) {
    clearInterval(timer);
  }
};

var timer = setInterval(count, 1000);

Once the callback function count notices the counter passed the value 10 it will stop the periodic timer whose ID was saved in the variable timer when setting it up.

mvw
  • 5,075
  • 1
  • 28
  • 34
  • If you're going to provide an answer, why don't you show the correct way to call `setTimeout()`? – jfriend00 Sep 11 '15 at 21:41
  • You also need to fix the [infamous loop issue](http://stackoverflow.com/questions/1451009/javascript-infamous-loop-issue) – Barmar Sep 11 '15 at 21:42
  • Obviously, the function passed to `setTimeout` captures (closes over) `i` and `10` is going to get logged 10 times. – jrsala Sep 11 '15 at 21:42